Im creating an application in java swing and in it Im making what I think is called an embedded Jpanel which is to my understanding a jpanel inside a jpanel. To make this simpler we will use the panel names there is content, sidebar, and content sidebar
Sidebar is just the sidebar for the application with buttons
Content is the main content of the app
Content sidebar is a side bar inside of content, I use this so my settings page has its own side bar apart from the normal side bar.
I make sidebar aligned to WEST and content CENTER
after content.add(contentSidebar, BorderLayout.WEST); it won't make content sidebar go to west and im not sure why.
this is my source code
package Assets.Settings;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Security implements ActionListener{
JFrame Security;
JPanel sideBar;
JPanel content;
//for sidebar
JButton volume;
JButton security;
JButton contactUs;
JPanel contentSidePanel;
// JButton twoStep;
// JButton changePassword;
public void security(){
Security = new JFrame();
sideBar = new JPanel();
content = new JPanel();
contentSidePanel = new JPanel();
sideBar.setPreferredSize(new Dimension(125, 700));
content.setPreferredSize(new Dimension(1000, 700));
content.setBackground(Color.YELLOW);
Security.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Security.setTitle("Anonyomail Security Settings");
Security.setSize(1152, 700);
Security.setLayout(new java.awt.BorderLayout());
contentSidePanel.setLayout( new java.awt.BorderLayout());
volume = new JButton();
security = new JButton();
contactUs = new JButton();
// twoStep = new JButton();
// changePassword = new JButton();
volume.addActionListener(this);
contactUs.addActionListener(this);
volume.setText("Volume");
security.setText("Security");
contactUs.setText("Contact Us");
// changePassword.setText("Change Password");
// twoStep.setText("2-Step");
security.setBackground(Color.decode("#24a0ed"));
contentSidePanel.setPreferredSize(new Dimension(100, 700));
contentSidePanel.setBackground(Color.BLACK);
// contentSidePanel.add(changePassword);
// contentSidePanel.add(twoStep);
content.add(contentSidePanel, BorderLayout.WEST);
sideBar.add(volume);
sideBar.add(security);
sideBar.add(contactUs);
Security.add(sideBar, BorderLayout.WEST);
Security.add(content, BorderLayout.CENTER);
Security.pack();
Security.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == volume){
//open volume
}else if(e.getSource() == contactUs){
//open contact us
}
}
}
EDIT
The issue is that I didn't give content a border layout
You call content.add(contentSidePanel, BorderLayout.WEST) however you never set content's layout manager to BorderLayout. I believe JPanel's default layout manager is FlowLayout and thus BorderLayout.WEST implies nothing.
On another note, it seems like you're only adding one thing, contentSidePanel, to content. I believe that BorderLayout will size content to the same size as contentSidePanel and that specifying BorderLayout.WEST will have no effect since there is nothing in the center or to the east. Try adding a test JPanel to content and setting it's layout to BorderLayout.CENTER to see if I'm correct.
Note: BorderLayout's position constants where updated in JDK 1.4 from compass positions (NORTH, EAST, ...) to wordier constants (PAGE_START, PAGE_END, LINE_START, LINE_END and CENTER). Therefor the use of BorderLayout.WEST should be replaced with BorderLayout.LINE_START. - from How to use BorderLayout
Related
I am creating a user system to hold multiple details of multiple users. so i would like to create a button that would be able to create another button. when the second button is pressed a form will open for the user to fill. I have already created the form for the user to fill but i cannot manage to make the button to create more buttons to work. I have coded this but it does not show the button on the Jpanel.
I have created the following code:
private void mainButtonActionPerformed(java.awt.event.ActionEvent evt) {
JButton b=new JButton("Click Here");
b.setBounds(50,100,95,30);
jPanel3.add(b);
b.setVisible(true);
}
This doesn't seem to create a new button within jPanel3. Have I typed up the code incorrectly or is there an alternative correct way of doing this?
I would like 3 buttons in a row and then a new row of buttons.
Your code and question is missing too much information to be answered completely or well. About all I can say is
Always call jPanel3.revalidate() and jPanel3.repaint() on the container after adding or removing components from it as this tells the container's (here jPanel3) layout managers to re-layout all components and then re-draw them.
The container's layout manager is key for this to work well -- we have no idea what it is at the moment, and some layout managers will allow you to do this easily (e.g., FlowLayout, GridLayout) while others won't (e.g., GroupLayout).
There's no need for b.setVisible(true); since your newly created JComponent (JButton here) is already visible by default.
You appear to assume that it's using null layouts since you're calling setBounds(...), and this is a Bad Idea™. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
When asking such questions, try to create and post with the question a small but complete program that we can test and run, and that illustrates your problem, a minimal example program (please click on the link).
For example, my MCVE that shows how your code can work:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class AddButton extends JPanel {
private JPanel jPanel3 = new JPanel(); // panel to hold buttons
public AddButton() {
// create JButton that will add new buttons to jPanel3
JButton addMoreButtonsBtn = new JButton("Add More Buttons");
// give it an ActionListener
addMoreButtonsBtn.addActionListener(e -> {
final JButton newButton = new JButton("Click Here");
// when you click it, it removes itself (just for grins)
newButton.addActionListener(e2 -> {
jPanel3.remove(newButton);
// again revalidate and repaint
jPanel3.revalidate();
jPanel3.repaint();
});
// add to jPanel3, the "container"
jPanel3.add(newButton);
// revalidate and repaint the container
jPanel3.revalidate();
jPanel3.repaint();
});
// create a JPanel and put the add more buttons button to it
JPanel bottomPanel = new JPanel();
bottomPanel.add(addMoreButtonsBtn);
// give jPanel3 a layout that can handle new buttons
// a gridlayout with 1 column and any number of rows
jPanel3.setLayout(new GridLayout(0, 1));
// add it to the top of another JPanel that uses BorderLayout
JPanel borderLayoutPanel = new JPanel(new BorderLayout());
borderLayoutPanel.add(jPanel3, BorderLayout.PAGE_START);
// and add that to a JScrollPane, so we can add many buttons and scroll
JScrollPane scrollPane = new JScrollPane(borderLayoutPanel);
// make the vert scrollbar always visible
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// force GUI to be larger
setPreferredSize(new Dimension(400, 200));
// give the main JPanel a BorderLayout
setLayout(new BorderLayout());
// and add scrollpane to center
add(scrollPane, BorderLayout.CENTER);
// add bottom panel to the bottom
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
AddButton mainPanel = new AddButton();
JFrame frame = new JFrame("AddButton");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I'm trying to center an image and position text to south in a border layout.
Here's what I have so far
import java.awt.BorderLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FlowWindow extends JFrame {
public FlowWindow() {
Container contentPane = getContentPane();
JPanel PanelImage = new JPanel();
JPanel PanelText = new JPanel();
contentPane.setLayout(new FlowLayout());
This Section is where the image is supposed to be centered in the border.
//calls the image and displays it to screen
//supposed to center it also
ImageIcon imageIcon = new
ImageIcon(getClass().getResource("WITlogo.JPG"));
JLabel label = new JLabel(imageIcon);
PanelImage.add(label);
contentPane.add(PanelImage, BorderLayout.CENTER);
This section is where the text is supposed to be position south in the border.
//creates the string of text and displays to screen
//supposed to position it in the south section of the border
contentPane.add(new JLabel("Waterford Institude of technology"));
PanelText.add(label);
contentPane.add(PanelText, BorderLayout.SOUTH);
}
public static void main(String args[]) {
FlowWindow window = new FlowWindow ();
window .setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("FlowWindow ");
window.pack();
window.setVisible(true);
window .show();
}
}
The easiest way to center a component is to use a GridBagLayout:
JPanel center = new JPanel( new GridBagLayout() );
JLabel imageLabel = new JLabel(...);
center.add(image, new GridBagConstraints());
JLabel textLabel = new JLabel(...);
Then you add your components to the frame using:
add(imageLabel, BorderLayout.CENTER);
add(textLabel, BorderLayout.PAGE_END);
Im really new to this
Then start by reading the section from the Swing tutorial on Layout Managers for working examples that show the basics.
Don't forget to look at the tutorial table of contents for more information on all Swing basics.
You are using a FlowLayout and adding stuff using BorderLayout constraints (for example BorderLayout.SOUTH).
If you want an centered picture with text just below you need to have a panel inside another panel.
I'm new to Swing and I currently work on some sort of graphic editor.
First I started implementing the toolbar (class OptionsBar) as an extended JPanel. Everything looked fine(image below), but it didn't work as a toolbar (it wasn't always focused). Then I found out that there actually exists a JToolBar element, so I replaced "extends JPanel" with "extends JToolBar". I look thorugh toolbar specifications. It seemed like I should change anything.
The problem is that the toolbar is transparent (besides its panel elements) even though isBackgroundSet() returns true. (image 2)
The second bug is drag the toolbar and then bring it back to the initial positions. It shrinks. (image 3)
Also, some movements (i can't describe them exactly) result in java.lang.IllegalArgumentException: illegal component position
The main windows is a JFrame that has border layout and uses a desktop pane.
Any help? Thanks!!
public class OptionsBar extends JToolBar {
..some constants and attributes..
public OptionsBar(BrushStroke brushStroke, BrushStroke savedBrushStroke) {
super();
this.setBackground(backgroundColor);
// keep the references to strokes from the main gui
this.brushStroke = brushStroke;
this.savedBrushStroke = savedBrushStroke;
// create buttons for selecting pencil/eraser
JToggleButton brushButton = makeInstrumentButton(brushIcon, "Pencil");
JToggleButton eraserButton = makeInstrumentButton(eraserIcon, "Eraser");
// make a button for adjusting colors
JButton adjustColorButton = makeAdjustButton();
// create label for descriptions
JLabel toolsLabel = makeDescriptionLabel("Tools");
JLabel parametersLabel = makeDescriptionLabel("Parameters");
JLabel colorsLabel = makeDescriptionLabel("Colors");
// create panel for brush size and opacity parameters
ParameterPanel sizePanel = new ParameterPanel("Size", "1", 1,
maxBrushSize, 1);
ParameterPanel opacityPanel = new ParameterPanel("Opacity", "100", 0,
100, 100);
// create a check box for selecting rounded caps
JCheckBox roundedCap = new JCheckBox("Use round strokes");
roundedCap.setSelected(true);
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
separator.setMaximumSize(new Dimension(3, 35));
JSeparator separator1 = new JSeparator(JSeparator.VERTICAL);
separator1.setMaximumSize(new Dimension(3, 35));
// create a box layout
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
this.add(Box.createHorizontalStrut(20));
this.add(toolsLabel);
this.add(Box.createHorizontalStrut(30));
this.add(brushButton);
this.add(Box.createHorizontalStrut(10));
this.add(eraserButton);
this.add(Box.createHorizontalStrut(30));
this.add(separator1);
this.add(Box.createHorizontalStrut(30));
this.add(parametersLabel);
this.add(Box.createHorizontalStrut(20));
this.add(sizePanel);
this.add(Box.createHorizontalStrut(20));
this.add(opacityPanel);
this.add(Box.createHorizontalStrut(25));
this.add(roundedCap);
this.add(Box.createHorizontalStrut(25));
this.add(separator);
this.add(Box.createHorizontalStrut(30));
this.add(colorsLabel);
this.setOpaque(false);
addColorButtons();
this.add(Box.createHorizontalStrut(20));
this.add(adjustColorButton);
this.colorPicker = new ColorPicker();
colorPicker.getSelectionModel().addChangeListener(new ColorChange());
this.colorPopup = new JPopupMenu();
colorPopup.add(colorPicker);
this.setSize(2000, 65);
this.setVisible(true);
}
And here is the snipped from the JFrame constructor
Here is a snippet from the JFrame constructor
desktop = new JDesktopPane();
setContentPane(desktop);
whiteBoards = new HashMap<String, Canvas>();
createFrame("first try", 400, 300);
desktop.add(new OptionsBar(brushStroke,savedBrushStroke),BorderLayout.PAGE_START);
To give an answer to all your questions:
JMenuBar is transparent by default. You can change that setting as follows:
menuBar.setOpaque(true);
You added your JMenuBar to a JDesktopPane container. A JDesktopPane has no layout set by default, to allow positioning of the added JInternalFrame. Thats why your JMenuBar is not visible, if you do not set the size manually.
Usually it is a better idea to let the LayoutManager align your components. To do so, replace your last code snippet with these lines:
desktop = new JDesktopPane();
JPanel basePanel = new JPanel(new BorderLayout());
basePanel.add(desktop, BorderLayout.CENTER);
basePanel.add(new OptionsBar(...), BorderLayout.PAGE_START);
getContentPane().add(basePanel);
This code uses another parent JPanel which allows us to add our JMenuBar to the top area. Aligning and sizing of our JMenuBar is not delegated to the LayoutManager of the JPanel so we can get rid of the getSize(...) in the constructor of the OptionsBar.
I am pretty sure that this change also fixes the thrown IllegalArgumentException.
I just wrote a simple code where I want a textfield and a button to appear on the main frame, but after running all I see is the textfield.
If I write the code of the button after the textfield then only the button is displayed.
Any idea why?
JFrame mainframe=new JFrame();
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setBounds(0,0,200,200);
JButton jb=new JButton();
jb.setText("Leech");
mainframe.add(jb);
JTextField link=new JTextField(50);
mainframe.add(link);
mainframe.pack();
mainframe.setVisible(true);
The default layout on a JFrame is a BorderLayout. Calling the add method on a Container with such a layout is equivalent to a call add(..., BorderLayout.CENTER). Each of the locations of the BorderLayout can contain only one element. Hence making two calls
mainframe.add(jb);
mainframe.add(link);
results in a CENTER containing the last component you added. If you want to avoid this you can either add it to different locations, or use another layout manager (for example a FlowLayout) by calling JFrame#setLayout
Instead of adding directly Components to the JFrame, use a JPanel as container with the desired LayoutManager.
Here you can find several tutorials on layout managers.
Basically in Swing the LayoutManager is responsible for laying out the children Components (establishing their position and their size), so every container component you use inside your app, should be configured with the appropiate LayoutManager.
Add your components to a JPanel and then add that panel to the ContentPane of JFrame.
JFrame window = new JFrame();
JPanel mainframe = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(0,0,200,200);
JButton jb = new JButton();
jb.setText("Leech");
mainframe.add(jb);
JTextField link = new JTextField(50);
mainframe.add(link);
window.getContentPane().add(mainframe);
window.pack();
window.setVisible(true);
You can also use something like Flow Layout which is the default layout used by JPanel. It is used to arrange components in a line or a row. For example from left to right or from right to left:
Flow layout arranges components in line and if no space left all remaining components goes to next line. Align property determines alignment of the components as left, right, center etc.
To use it you will need to set JFrame layout by using JFrame.setLayout(layout) and to pass flow layout as a parameter.
Following example shows components arranged in flow layout:
package example.com;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class FlowLayoutExample {
FlowLayoutExample(){
JFrame frame = new JFrame("Flow Layout");
JButton button, button1, button2, button3, button4;
button = new JButton("button 1");
button1 = new JButton("button 2");
button2 = new JButton("button 3");
button3 = new JButton("button 4");
button4 = new JButton("button 5");
frame.add(button);
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.setLayout(new FlowLayout());
frame.setSize(300,300);
frame.setVisible(true);
}
public static void main(String[] args) {
new FlowLayoutExample();
}
}
Check out to learn more about JFrame layouts.
JFrame's default Layout Manager is BorderLayout. If you want the automatic layout, you may use the FlowLayout:
mainframe.setLayout(new FlowLayout());
If you want to specify coordinates by setBounds() method, you have to cancel the setting of layout manager on JFrame:
mainframe.setLayout(null);
jb.setBounds(10,10,100,50);
link.setBounds(10,70,180,100);
if you see BorderLayout Documentation
mainframe.add(jb); is equals to mainframe.add(jb,BorderLayout.CENTER);
mainframe.add(link); is equals to mainframe.add(jb,BorderLayout.CENTER);
so it just show the last one
so i have a problem i cant solve i want my GUI app to be split between 3 JPanels (left, center, right). I want left panel and right panel to be of fixed size and center to be fluid. Meaning side panels expand only vertically as JFrame is expanded and center panel expands bot horizontally and vertically.
I have set minimal size for all panels to be height of 600 but they just stay in the minimal size and dont expand as JForm increases i dont know how to set bounds to JFrame borders so they expand whit it.
package ppe.view;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import net.miginfocom.swing.MigLayout;
public class UI_View extends JFrame
{
private JList browse = new JList();
private JScrollPane rightX = new JScrollPane();
private JButton btn1 = new JButton("Button 1");
private JButton btn2 = new JButton("Button 2");
private JButton btn3 = new JButton("Button 3");
private JButton btn4 = new JButton("Button 4");
public UI_View()
{
this.setTitle("Prototype MVC Arhitecture");
this.setMinimumSize(new Dimension(800, 600));
this.setExtendedState(this.MAXIMIZED_BOTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new MigLayout());
JPanel content = new JPanel(new MigLayout());
content.setBackground(Color.black);
JPanel right = new JPanel(new MigLayout());
JPanel center = new JPanel(new MigLayout());
JPanel left = new JPanel(new MigLayout());
right.setBackground(Color.red);
right.setMinimumSize(new Dimension(200, 600));
right.setMaximumSize(new Dimension(200, 37500));
center.setBackground(Color.green);
center.setMinimumSize(new Dimension(400, 600));
left.setBackground(Color.blue);
left.setMinimumSize(new Dimension(200, 600));
left.setMaximumSize(new Dimension(200, 37500));
content.add(left);
content.add(center);
content.add(right);
this.setContentPane(content);
}
public static void main(String[] args)
{
new UI_View().setVisible(true);
}
}
I have tryed bounding them to another content panel and adding that panel as ContentPane to JFrame that automatically bounds it to JFrame border but the thing is still pretty much fixed.
If you're using MiGLayout why don't you configure the constraints when adding the components?
This, for example, might help (although I'm a MiGLayout beginner, too):
content.add(left, "growy");
content.add(center, "grow"); //the same as growx, growy
content.add(right, "growy");
In some cases I needed to also add a pushx but I'm not sure when this is needed. Please refer to the documentation for further information.
Edit: it seems like you always have to add push for components that should cause the column/row to grow. Otherwise grow alone would make the components as big as the column/row they are in which in turn is defined by the largest component in that column/row. If there is more space available columns/rows won't grow to fill it without the push keyword.
From the documentation:
Components will never "push" the column/row's size to be larger using the grow keyword.