Reputation: 68
I have a JPanel containing a few components, laying them out with a FlowLayout, so that they will wrap if necessary and i want to center this JPanel in a JFrame. I tried to use a BoxLayout with a VerticalGlue, but it doesn't center it completely. Here is a simple SSCCE, which demonstrates my problem, because i dont think i can explain it well:
import javax.swing.*;
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
getContentPane().add(Box.createVerticalGlue());
JPanel panel = new JPanel();
panel.add(new JButton("New button"));
panel.add(new JButton("New button"));
getContentPane().add(panel);
setVisible(true);
}
}
If the window is wide enough to fit both buttons next to each other, it almost seems centered:
But if its too small you can clearly see my problem:
The problem is that the JPanel takes the lower half of the JFrame and the Glue the upper half:
I have tried other LayoutManagers aswell, but I couldn't fix this problem yet.
EDIT:
With a BorderLayout and the JPanel placed in the center the buttons appear at the top because the JPanel expands to the size of the ContentPane of the JFrame:
With a GridBagLayout it looks perfect with everything next to each other. But if the components are wrapped they disappear:
Using a MigLayout, the buttons wont wrap anymore:
EDIT: The solution i used is a combination of the Wrap Layout with the GridBagLayout:
import java.awt.*;
import javax.swing.*;
class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWeights = new double[]{1.0};
getContentPane().setLayout(gridBagLayout);
JPanel panel = new JPanel(new WrapLayout());
GridBagConstraints gbc_panel = new GridBagConstraints();
gbc_panel.fill = GridBagConstraints.HORIZONTAL;
getContentPane().add(panel, gbc_panel);
panel.add(new JButton("New button"));
panel.add(new JButton("New button"));
setVisible(true);
}
}
Upvotes: 1
Views: 3721
Reputation: 5560
Here is an example using the WrapLayout mentioned by camickr. I had to mess with max size of the wrap panel which is a bit of a hack, but I think it's enough to get you pointed in the right direction.
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel boxPanel = new JPanel();
boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.Y_AXIS));
boxPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN, 1));
JPanel wrapPanel = new JPanel();
// hack of panel max size
wrapPanel.setMaximumSize(new Dimension(99999, 0));
wrapPanel.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
wrapPanel.setLayout(new WrapLayout(FlowLayout.CENTER));
wrapPanel.add(new JButton("New button"));
wrapPanel.add(new JButton("New button"));
boxPanel.add(Box.createGlue());
boxPanel.add(wrapPanel);
boxPanel.add(Box.createGlue());
add(boxPanel, BorderLayout.CENTER);
setVisible(true);
}
}
Upvotes: 1
Reputation: 324098
The problem is that the JPanel takes the lower half of the JFrame and the Glue the upper half:
The problem is that the BoxLayout will allow components to grow up to the maximum size of the component. In the case of a panel, the maximum size is the maximum Integer value so both the glue and the panel get equal amounts of space. So if you want to use a BoxLayout, you need to override the getMaximumSize()
method to return the preferred size of the panel.
I tried to use a BoxLayout with a VerticalGlue, but it doesn't center it completely.
After the above change you then need to use verticalGlue twice:
Box box = new Box.createVerticalBox();
box.add( Box.createVerticalGlue() );
box.add( panel );
box.add( Box.createVerticalGlue() );
Now you will have equal amounts of space above and below the panel. However, this still won't work when components wrap to the next line because the FlowLayout
does not recalculate the height based on the wrapped components. So in this case you can replace the FlowLayout
with the Wrap Layout which simply extends FlowLayout
to calculate the wrapped height correctly.
Or instead of using a BoxLayout, you can use a GridBagLayout. By default components added to the GridBagLayout will be centered horizontally and vertically. You would still need the panel with the WrapLayout
Upvotes: 4
Reputation: 453
You can center a JPanel containing a FlowLayout by this code
setLayout(new FlowLayout(FlowLayout.CENTER));
Upvotes: 0