Java GUI Logic - Not understanding adding to JFrame - java

I have a pretty straight forward question. Can some please please explain to me why the following JFrame is not showing Hello (100,100 pixels on the left side of the screen and World (100,100 pixels) on the right side of the screen since I am using border layout.
I created a JFrame
Assigned it a layout of borderlayout
Created 2 panels with 2 labels and assigned the panels to be aligned left and right.
added the panels to the JFrame
Displayed the JFrame
What am I missing?
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 500);
frame.setLayout(new BorderLayout());
frame.setVisible(true);
JPanel panel1 = new JPanel();
panel1.setPreferredSize(new Dimension(100,100));
panel1.setBackground(Color.BLUE);
JLabel label1 = new JLabel("Hello");
label1.setBackground(Color.YELLOW);
label1.setForeground(Color.WHITE);
panel1.add(label1,BorderLayout.LINE_START);
frame.add(panel1);
JPanel panel2 = new JPanel();
panel2.setPreferredSize(new Dimension(100,100));
panel2.setBackground(Color.RED);
JLabel label2 = new JLabel("World");
label2.setBackground(Color.CYAN);
label2.setForeground(Color.WHITE);
panel2.add(label2,BorderLayout.LINE_END);
frame.add(panel2);

You are setting the Layout-Constraints on the wrong panel.
Instead of panel2.add(label2,BorderLayout.LINE_END); it should be panel2.add(label2) and instead of frame.add(panel2); it should be frame.add(panel2, BorderLayout.LINE_END);.
Same for panel1.

Related

JPanel won't show in JFrame

I'm trying to create a JPanel (non-resizable) showing a grid of buttons but when I try to add the JPanel to a JFrame it won't show.
JFrame frame = new JFrame("frame");
JPanel panel = new JPanel();
frame.setSize(681,920);
frame.setResizable(true);
JLabel label = new JLabel();
label.setLayout(new FlowLayout(FlowLayout.LEADING,0,0));
JButton btn = new JButton();
btn.setContentAreaFilled( false );
btn.setBorder( null );
btn.setBounds(214,210,0,0);
label.add(btn);
panel.add(label);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
The output should be a resizable frame with inside a 3x4 grid of buttons.
If I don't use the panel and I put the line frame.setResizable(false) it works as expected but I need to add more stuff to the frame so I need to put the buttons safe in a panel.
Both panel and label are added to your frame, to make sure they are added write
JLabel label = new JLabel("JLABEL");
and
panel.setBackground(Color.BLUE);

Swing GUI problems with BorderLayout

I'm currently trying to get along with Layouts, considering that I never really understood them and only did nullLayout instead, absolutely positioning all elements then.
However, I currently have a suitable small project, where I am trying to learn it, which is some small chat service.
Here is a picture right now:
And here is a picture, of how I imagine it to be finished (Please note that this is just some concept, but it should give you the right idea. I'm not a graphic artist):
Here is my current code:
public class Gui {
JFrame frame;
JTextArea textfield;
JTextField enterMessage;
public Gui(){
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
textfield.setSize(400, 300);
JPanel messagePanel = new JPanel();
JTextField chatMessage = new JTextField();
chatMessage.setText("Send me");
JButton send = new JButton();
send.setText("Send");
messagePanel.add(chatMessage, BorderLayout.WEST);
messagePanel.add(send, BorderLayout.EAST);
frame.add(textfield, BorderLayout.WEST);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
My idea, together with the understanding of BorderLayouts so far was to put the Textfield, where the chat dialog ends up in later on, right inside the frame, on the WEST-side.
The button to send and the field to enter some text will be inside a panel, with an own borderlayout, while the button has some smaller part on the right and the rest of the width is being filled with the textfield.
The whole panel then ends on the SOUTH-side of the frame.
However, right now I have the problem, that the elements keep shrinking to the least possible size.
I tried to fix this with setSize(); , but that does not have an impact at all, it is just being completely ignored.
Any help to point me into the right direction?
Initially, you've got one simple problem:
// should be new JPanel(new BorderLayout())
JPanel messagePanel = new JPanel();
Then, after that, generally BorderLayout likes to stretch the component in BorderLayout.CENTER. So you want to put your textfield and chatMessage in the center.
public Gui(){
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
// textfield.setSize(400, 300);
JPanel messagePanel = new JPanel(new BorderLayout());
JTextField chatMessage = new JTextField("Send me");
JButton send = new JButton("Send");
messagePanel.add(chatMessage, BorderLayout.CENTER);
messagePanel.add(send, BorderLayout.EAST);
frame.add(textfield, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
Once you do that, you should get something like this:
But, as a few words of advice:
Don't rely on setSize of a JFrame. Instead, you should use setPreferredSize on a single component which the entire UI should size itself around. (Probably the main text area.) The size of a JFrame includes, for example, the title bar.
You should consider wrapping your JTextArea in a scroll pane. You can then instead setPreferredSize on the viewport.
After you have a component with a preferred size, call pack() on the JFrame before calling setVisible(true). This will size it automatically.
Something like:
frame = new JFrame();
// frame.setSize(600, 400);
...
JScrollPane pane = new JScrollPane(
textfield,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// specifying initial size for the
// visible portion of the scroll pane
pane.getViewport().setPreferredSize(new Dimension(320, 200));
frame.add(pane, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
// entire UI sizes around the scroll pane view
frame.pack();
frame.setVisible(true);
Try BoxLayout insted BorderLayout in messagePanel:
messagePanel.setLayout(new BoxLayout(messagePanel,BoxLayout.LINE_AXIS));
messagePanel.add(chatMessage);
messagePanel.add(send);
And for textField:
frame.add(textfield, BorderLayout.CENTER);
Try setting preferred size dimensions of the elements.
textfield.setText("Textfield");
textfield.setPreferredSize(new Dimension(600, 300));
//some other code
JTextField chatMessage = new JTextField();
chatMessage.setPreferredSize(new Dimension(500, 25));
//some other code
As pointed out by Sridhar, BorderLayout does not always respect the dimensions of sub-panels. To fix this, you should initialize your sub-panels (in this case textfield and messagePanel) using setPreferedSize() instead of setSize().
change your constructor to
public Gui() {
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
textfield.setSize(400, 300);
// set border layout to JPanel
JPanel messagePanel = new JPanel(new BorderLayout());
JTextField chatMessage = new JTextField();
chatMessage.setText("Send me");
JButton send = new JButton();
send.setText("Send");
// add JTextField to CENTER and button to EAST
messagePanel.add(chatMessage, BorderLayout.CENTER);
messagePanel.add(send, BorderLayout.EAST);
// add textArea to CENTER of JFrame
frame.add(textfield, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
and it will work..

Boxlayouts with JPanels incorrectly expanding with resize

I've searched a fair amount and I cannot locate a good, simple answer to this problem.
I want a box layout (superPanel), which contains an upper and lower JPanel (mainPanel and footerPanel). The upper will contain further JPanels (leftPanel and rightPanel).
Consider the code below, I find that when I resize the window, the mainPanel gets larger, and so does the footer. The footer should always stay the same size, below the mainPanel, at the bottom of the frame.
frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
JPanel superPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel= new JPanel();
JPanel footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
mainPanel.setBackground(Color.RED);
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
mainPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
leftPanel.add(new JButton("left"));
rightPanel.add(new JButton("right"));
footerPanel.add(new JButton("footer"));
container.add(mainPanel);
container.add(footerPanel);
frame.add(container);
frame.pack();
frame.setVisible(true);
Anybody know why this is occurring? If you run this you'll see that red and green both grow in size as the window is resized. What I want to see is the red getting larger, while the green remains the same size.
Glue doesn't work, and I don't want to have to use GridBagLayout unless I have to (please explain why I should if need be)
Thanks
When you want a "main" section and side sections which don't change size, you usually want a BorderLayout:
container.setLayout(new BorderLayout());
container.add(mainPanel, BorderLayout.CENTER);
container.add(footerPanel, BorderLayout.PAGE_END);
Try to use GridBagLayout with fill.BOTH, weightx = 1 and weighty = 1 for the main panel and fill.NONE, weightx = 0 and weighty = 0 for the footer panel or use Miglayout which is really easy and with it you can do all what you want.
BorderLayout is what you want on your container, adding the mainPanel to the center and footerPanel to the south. Try the following changes on your code:
frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.setLayout(new BorderLayout()); // Use BorderLayout instead of BoxLayout
JPanel superPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JPanel footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
mainPanel.setBackground(Color.RED);
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
mainPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
leftPanel.add(new JButton("left"));
rightPanel.add(new JButton("right"));
footerPanel.add(new JButton("footer"));
container.add(mainPanel, BorderLayout.CENTER); // Add mainPanel to the central area
container.add(footerPanel, BorderLayout.SOUTH); // Add footePanel to the bottom
frame.add(container);
frame.pack();
frame.setVisible(true);
The BorderLayout determines that a component added to the CENTER area will expand both horizontally and vertically to follow the container. The SOUTH area can only expand horizontally while EAST and WEST can only expand vertically. Keep in mind that every layout manager class has its own rules on how to divide the container space among components and how they are resized.

How to center a component on a row containing multiple components with MiGLayout

I started using MiGLayout about a month and half ago and everything is simple and works great. There's only one issue I still have that I haven't been able to fix.
Let's say I want to have a row that has two buttons on the right-most side and a centered title, the title doesn't actually get centered when I do it this way:
("this" is a JPanel)
this.add(labelTitle, "split, span, center");
this.add(closeButton, "east");
this.add(mainMenuButton, "east");
What happens is that "labelTitle" is centered in the remaining space available after the buttons are placed, but I actually want it to be centered relative to the whole JPanel, not just the remaining space.
What parameters could I use to get the desired effect? I know I could use absolute positioning, but I don't want to do that because it defeats the purpose of using MiGLayout in the first place in my case.
Can it be something like this you are looking for?
Cheers!
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel panel = new JPanel(new MigLayout("debug"));
panel.add(new JLabel("Label Title"), "x2 min(b1.x - unrel, (container.w+pref)/2)");
panel.add(new JButton("Close Button"), "id b1, pushx, alignx right");
panel.add(new JButton("Main Menu Button"), "alignx right");
frame.add(panel);
frame.setSize(800, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
You can use the JXLayer and put the buttons in the glasspane.
JButton closeButton = new JButton("Close");
JButton mainMenuButton = new JButton("Menu");
JLabel labelTitle = new JLabel("Application");
JPanel panel = new JPanel();
panel.setLayout(new MigLayout(new LC().fillX()));
panel.add(labelTitle, new CC().alignX("center").spanX());
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new MigLayout(new LC().fillX()));
buttonPanel.add(closeButton, new CC().alignX("right").split());
buttonPanel.add(mainMenuButton, new CC().alignX("right"));
buttonPanel.setOpaque(false);
JXLayer<JPanel> mainPanel = new JXLayer<JPanel>();
mainPanel.setView(panel);
mainPanel.setGlassPane(buttonPanel);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.setSize(400, 600);
frame.setVisible(true);
When creating your JPanel, use the following MigLayout initializer:
new MigLayout("","[]push[center]push[]","")
If you don't know about constraints, check here: MigLayout Whitepaper
This is assuming you don't have anything else in this JPanel...

error upon assigning Layout: BoxLayout can't be shared

I have this Java JFrame class, in which I want to use a boxlayout, but I get an error saying java.awt.AWTError: BoxLayout can't be shared. I've seen others with this problem, but they solved it by creating the boxlayout on the contentpane, but that is what I'm doing here. Here's my code:
class EditDialog extends JFrame {
JTextField title = new JTextField();
public editDialog() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("New entity");
getContentPane().setLayout(
new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(title);
pack();
setVisible(true);
}
}
Your problem is that you're creating a BoxLayout for a JFrame (this), but setting it as the layout for a JPanel (getContentPane()). Try:
getContentPane().setLayout(
new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS)
);
I've also found this error making this:
JPanel panel = new JPanel(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
The JPanel isn't initialized yet when passing it to the BoxLayout. So split this line like this:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
This will work.
I think that one important thing to highlight from the previous answers is that the BoxLayout's target (the first parameter) should be the same Container that the setLayout method is being called upon as in the following example:
JPanel XXXXXXXXX = new JPanel();
XXXXXXXXX.setLayout(new BoxLayout(XXXXXXXXX, BoxLayout.Y_AXIS));
If you're using the layout on a JFrame like:
JFrame frame = new JFrame();
frame.setLayout(new BoxLayout(frame, BoxLayout.Y_AXIS));
frame.add(new JLabel("Hello World!"));
The control is actually being added to the ContentPane so it will look like it's 'shared' between the JFrame and the ContentPane
Do this instead:
JFrame frame = new JFrame();
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
frame.add(new JLabel("Hello World!"));

Categories