I have the following layout:
The red, blue and green parts are JPanel. In the red part I have four JLabel. Now if I resize the JFrame, the title labels always stay in the center. But I would prefer if they are evenly distributed horizontaly in the red part. Which layout should I use for that?
Use a GridLayout(1, 0) for the top JPanel. The two numbers means 1 row and variable number of columns. If you are using JLabels, this will be sufficient, especially if you set the JLabels alignment constant to SwingConstants.CENTER. If you are using components that fill the grid slots, such as JButtons, then you may need to use other variants of the GridLayout constructor, such as GridLayout(1, 0, ?, 0) Where the ? is a number that tells the GridLayout how much horizontal separation there should be between slots.
The overall GUI would use a BorderLayout of course.
For more and better information on this, please check out Lesson: Laying Out Components Within a Container and A Visual Guide to Layout Managers
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
public class LayoutEg {
private static void createAndShowGui() {
String[] labelStrings = {"One", "Two", "Three", "Four"};
JPanel topPanel = new JPanel(new GridLayout(1, 0));
for (String labelString : labelStrings) {
// create labels and center the text
topPanel.add(new JLabel(labelString, SwingConstants.CENTER));
}
topPanel.setBackground(Color.red);
JPanel centerPanel = new JPanel();
centerPanel.setBackground(Color.blue);
// setting preferred size for demonstration purposes only
centerPanel.setPreferredSize(new Dimension(700, 400));
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(Color.green);
// main panel uses BorderLayout
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(topPanel, BorderLayout.PAGE_START);
mainPanel.add(bottomPanel, BorderLayout.PAGE_END);
JFrame frame = new JFrame("LayoutEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Use a BorderLayout for the frame's content pane, and use a GridLayout with 1 row and four columns for the title panel.
See http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html and http://docs.oracle.com/javase/tutorial/uiswing/layout/grid.html for tutorials.
If you don't want the same width assigned to each label, but in fact want the same space between every label, you may also use a BoxLayout, and add a glue between each label (and between the border of the panel and the label:
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
p.add(Box.createHorizontalGlue());
p.add(new JLabel("Label"));
p.add(Box.createHorizontalGlue());
p.add(new JLabel("Long Label"));
p.add(Box.createHorizontalGlue());
p.add(new JLabel("Very long Label"));
p.add(Box.createHorizontalGlue());
p.add(new JLabel("Extremely long Label"));
p.add(Box.createHorizontalGlue());
Use a BorderLayout for the main frame and use the NORTH, CENTER and SOUTH places.
To create empty space like in the bottom panel, use Box.createVerticalStrut(size).
Use BoxLayout to place the labels packed in a row.
Finally use GridBagLayout to center a panel in another Panel.
Here is a short example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Prototype extends JFrame {
public Prototype() {
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.LINE_AXIS));
labelPanel.add(new JLabel("First"));
labelPanel.add(Box.createHorizontalStrut(10));
labelPanel.add(new JLabel("Second"));
labelPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
labelPanel.setOpaque(false);
JPanel bottomPanel = new JPanel();
bottomPanel.add(Box.createVerticalStrut(15));
bottomPanel.setBackground(Color.GREEN);
JPanel centerPanel = new JPanel();
centerPanel.add(Box.createRigidArea(new Dimension(200, 300)));
centerPanel.setBackground(Color.BLUE);
JPanel northPanel = new JPanel(new GridBagLayout());
northPanel.add(labelPanel);
northPanel.setBackground(Color.RED);
JPanel panel = new JPanel(new BorderLayout());
panel.add(northPanel, BorderLayout.NORTH);
panel.add(centerPanel, BorderLayout.CENTER);
panel.add(bottomPanel, BorderLayout.SOUTH);
add(panel);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Prototype();
}
}
Use a MigLayout.
No, seriously, I used to go crazy trying to get Java layouts working. Then I started maintaining some software that uses MigLayouts, and after a week or so I could do anything I wanted. There is an excellent cheat sheet that looks pretty intimidating, but it's incredibly helpful.
With a MigLayout, to have evenly spread labels in a JPanel you would:
// the "fillx" means that the layout will expand to take up all available horizontal space
JPanel panel = new JPanel(new Miglayout("fillx"));
// the "growx" means that the component will expand to take up all available horizontal space
add(new JLabel("Work items"), "growx");
add(new JLabel("Change set"), "growx");
add(new JLabel("Files"), "growx");
add(new JLabel("Source code"), "growx");
gridLayout, put the labels into the grid layout and set rows to 1 and columns to 4 (1 row for each Label)
http://www.javabeginner.com/java-swing/java-gridlayout-class-example
GridBagLayout is one approach. Set the weightx value to 1.0.
For labels to be distributed evenly horizantally - in the red panel - use BoxLayout with X_AXIS direction and put 'glue' between each label - More here -
http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
Related
I am using BorderLayout for my application.
setLayout(new BorderLayout());
I need to align two JLabels in left and right in the "NORTH" of the JPanel.
Here is my code:
JPanel top = new JPanel();
top.add(topTxtLabel);
top.add(logoutTxtLabel);
add(BorderLayout.PAGE_START, top);
So I need topTxtLabel in left and logoutTxtLabel in right.
I tried to implement Border Layout again to use "WEST" and "EAST", but it didn't worked. Ideas?
Assuming your application consists of a JFrame with BorderLayout you could try this: Set the layout mode of your JPanel again to BorderLayout. Add the panel in the north of the frame. Then add the 2 JLabels in the east and west. You can also replace the JFrame with another JPanel.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main
{
public static void main(String[] args)
{
new Main();
}
Main()
{
JFrame frame = new JFrame("MyFrame");
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel(new BorderLayout());
JLabel left = new JLabel("LEFT");
JLabel right = new JLabel("RIGHT");
JPanel top = new JPanel(new BorderLayout());
top.add(left, BorderLayout.WEST);
top.add(right, BorderLayout.EAST);
panel.add(top, BorderLayout.NORTH);
frame.add(panel, BorderLayout.NORTH);
frame.add(new JLabel("Another dummy Label"), BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I am trying to add multiple panels to another panel. I want them to be on top of each other so I'm using JLayeredPane. I've added a button to each one. Two buttons should appear when it works.
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class PanelTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JLayeredPane layers = new JLayeredPane();
mainPanel.add(layers);
panel2.setOpaque(false);
panel1.setOpaque(false);
panel1.setVisible(true);
panel2.setVisible(true);
panel1.add(new JButton("1111111111"));
panel2.add(new JButton("2"));
frame.setContentPane(mainPanel);
layers.add(panel1, new Integer(2));
layers.add(panel2, new Integer(3));
frame.setVisible(true);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Only the grey background of the mainPanel is visible. What am I doing wrong?
When adding a component to a JLayeredPane, you're essentially adding the component to a null layout using container. This means that you must fully specify both the component's size and its position, often solving both with a setBounds(...) call. Call this on panel1 and panel2, for example:
panel1.setBounds(10, 10, 100, 100);
panel2.setBounds(70, 70, 100, 100);
Edit:
setting bounds didn't make any difference
Setting the size (bounds) is required but you still have an additional problem.
You are adding the JLayeredPane to a JPanel which uses a FlowLayout. By default a FlowLayout respects the preferred size of the component added to it. Since JLayeredPane uses a null layout its preferred size is (0, 0) so there is nothing to paint.
Two solutions:
You don't need the JPanel, just use: frame.setContentPane(layers);
If you really want to use the panel then you need to change the layout manager: JPanel mainPanel = new JPanel( new BorderLayout());
Experimenting with layered panes here and I'm having a problem. I have two JPanels. I'm adding them both to a JLayeredPane - panel1 is big enough to take up the whole space, while panel2 is smaller and centered using FlowLayout. The problem is that with JLayeredPane, the background next to panel2 seems to be painted white when I add it. Here's a picture to illustrate. panel1 is blue, panel2 is red:
As you can see, the bottom part of the panel1 is still painted, but for some reason the sides are just white. The panel2 is 700 pixels wide and centered, while the frame is 800 pixels wide, so it's definitely not a problem with that. Here's the entire class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class Errortest extends JFrame {
public static void main(String[] args) {
//Creating frame and setting the JLayeredPane as contentpane
Errortest frame = new Errortest();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLayeredPane pane = new JLayeredPane();
pane.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
pane.setPreferredSize(new Dimension(800,600));
frame.setContentPane(pane);
frame.pack();
//Creating panels
JPanel panel1 = new JPanel();
panel1.setPreferredSize(new Dimension(800,600));
panel1.setBackground(Color.BLUE);
JPanel panel2 = new JPanel();
panel2.setPreferredSize(new Dimension(700,500));
panel2.setBackground(Color.RED);
pane.add(panel1, new Integer(0));
pane.add(panel2, new Integer(1));
frame.setVisible(true);
}
}
Hopefully that wasn't too confusing. From what I can tell, the white background comes from the JFrame itself, since when I do frame.setBackground(Color.YELLOW); it turns yellow.
If you add a component to a JLayeredPane, it's like adding it to a null layout using container: you must fully specify the component's size and position.
import java.awt.*;
import javax.swing.*;
public class ErrorTest extends JFrame {
public static void main(String[] args) {
// Creating frame and setting the JLayeredPane as contentpane
ErrorTest frame = new ErrorTest();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent pane = new JLayeredPane();
//pane.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); // Take out FlowLayout
pane.setPreferredSize(new Dimension(800, 600));
frame.setContentPane(pane);
// Creating panels
JPanel panel1 = new JPanel();
panel1.setBackground(Color.BLUE);
panel1.setBounds(0, 0, 800, 600); // <<<---- Set Bounds
JPanel panel2 = new JPanel();
panel2.setBackground(Color.RED);
panel2.setBounds(50, 0, 700, 500); // <<---- Set Bounds
pane.add(panel1, new Integer(1));
pane.add(panel2, new Integer(2));
frame.pack();
frame.setVisible(true);
}
}
I believe I found out what the problem is. Has to do with the answer here:
JLayeredPane not respecting layers
You need a layout manager which understands the Z-Axis. The default layout managers don't understand the Z-Axis of the JLayeredPane.
So it's the FlowLayout that's messing me up. I'll just use absolute positioning for my project and use setBounds() to make sure the red panel ends up in the middle. Otherwise I'd have to look into custom layout managers I suppose.
Here is my code to add to component (JTextArea and JList) to a panel and put it on the frame. Can I divide half/half by BorderLayout?
If yes why mine looks messy one stays up one down?
What is the other alternative?
Regards,
Bernard
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class SimpleBorder {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Border etched = (Border) BorderFactory.createEtchedBorder();
String[] items = {"A", "B", "C", "D"};
JList list = new JList(items);
JTextArea text = new JTextArea(10, 40);
JScrollPane scrol = new JScrollPane(text);
JScrollPane scrol2 = new JScrollPane(list);
JPanel panel= new JPanel();
panel.add(scrol2,BorderLayout.WEST);
panel.add(scrol, BorderLayout.EAST);
panel.setBorder(etched);
frame.add(panel);
frame.setVisible(true);
}
}
The default Layout manager for JPanel is FlowLayout, so adding components without actually setting the layout to an instance of BorderLayout will produce unexpected results.
To get a half/half layout you could use GridLayout:
JPanel panel= new JPanel(new GridLayout(1, 2));
You must use a different LayoutManager, BorderLayout will not allow you add components that use only 50% of the visible space. I personally use GridBagLayout, which allows you to specify many parameters (free space distribution, new lines of components, alignment, etc.).
You should set the LayoutManager of your JPanel to BorderLayout first (only ContentPanes i.e frame#getContentPane() have a default layout of BorderLayout):
JPanel panel= new JPanel(new BorderLayout());
panel.add(scrol2,BorderLayout.WEST);
panel.add(scrol, BorderLayout.EAST);
panel.setBorder(etched);
I have a problem with Java GUI.
I want to create three JPanel instances which have size different in one JFrame. JFrame size 300x800 and Panel1 300x200, Panel2 300x100 and Panel3 300x500. I want to add this panels under by under.
How to solve this problem?
Use a BorderLayout1.
Add panel1 to the NORTH
Add panel2 to the CENTER
Add panel3 to the SOUTH
E.G.
Stretch your imagination that the heights are ten times bigger.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class ColoredPanels {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel gui = new JPanel(new BorderLayout(3,3));
gui.setBackground(Color.BLUE);
gui.setBorder(new EmptyBorder(5,5,5,5));
JPanel panel1 = new JPanel();
panel1.setPreferredSize(new Dimension(300,20));
panel1.setBackground(Color.RED);
gui.add(panel1, BorderLayout.NORTH);
JPanel panel2 = new JPanel();
panel2.setPreferredSize(new Dimension(300,10));
panel2.setBackground(Color.ORANGE);
gui.add(panel2, BorderLayout.CENTER);
JPanel panel3 = new JPanel();
panel3.setPreferredSize(new Dimension(300,50));
panel3.setBackground(Color.YELLOW);
gui.add(panel3, BorderLayout.SOUTH);
// a frame would need pack() etc.
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
BTW
Use BorderLayout, ..or BoxLayout as mentioned by Shakedown.
The panels as described will not fit into the frame at that size. A frame has its own decorations to account for (title bar, menus, borders etc.)
Please use camelCase for attribute names.
You can try sizing your panels with setPreferredSize() and company.
Then look into using a BoxLayout on your frame, which will put your panels in a row or column.