Reputation: 1798
Trying to learn how to do some elegant and more advanced JFrame
layouts. I'm trying to make something I thought would be rather simple, but I'm having some difficulty with it. As opposed to messing around for hours (even though I already have) trying to get the layout to work, I thought I would ask what the best convention for a the layout I'm about to describe would be.
The Layout
Basically, I want 2 columns, but the first column to be wider than the second column. Within the first column there will be just one cell, and that cell will have a JLabel
with an icon attached to it, centered in the cell. The second column will have 4 rows, each with a JComponent
in it (doesn't matter what). Another key is that every component in the JFrame
retains its preferred size, and doesn't stretch to fit its cell or what have you.
Here's a picture of the desired layout:
So far I've thought of doing this a couple different ways:
BorderLayout
, with the JLabel
-icon in the center, and a GridLayout
/GridBagLayout
controlling the rest.GridBagLayout
4x4 where the JLabel
-icon takes up a 3x4 area, in theory giving it 75% of the space.Neither give me the results I'm looking for. Thoughts/Suggestions? All help and suggestions are greatly appreciated.
Upvotes: 1
Views: 1139
Reputation: 324128
Your first suggestion is reasonable.
The label can be centered both vertically and horizontally.
For the GridLayout the trick would be to add each component to a JPanel that uses a GridBagLayout with the default gridbag constraints. Then add the panel to the GridLayout. Now, if the frame does resize, the panel will grow, but not the component on the panel and the component will be centered in the panel.
Instead of using the GridLayout with other sub panels, you can also use a vertical BoxLayout and add "glue" before/after every component. Not that with this approach you will need to make sure every component uses an alignment that is centered. Also, you may need to set the maximum size of some components equal to the preferred size of the component so it doesn't grow when space is available.
Upvotes: 2
Reputation: 347244
For my own sanity, I would normally separate the individual elements of the layout. This can, sometimes, simplify the process as you only need to focus on the areas of the layout that are important (to each section).
The following example uses a single layout just to demonstrate the power of GridBagLayout
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AdvancedLayout {
public static void main(String[] args) {
new AdvancedLayout();
}
public AdvancedLayout() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel image;
private JButton button;
private JLabel label;
private JComboBox comboBox;
private JButton otherButton;
public TestPane() {
setLayout(new GridBagLayout());
image = new JLabel();
button = new JButton("A button");
label = new JLabel("A label");
comboBox = new JComboBox();
otherButton = new JButton("Other");
try {
image.setIcon(new ImageIcon(ImageIO.read(new File("/path/to/a/image"))));
} catch (IOException ex) {
ex.printStackTrace();
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.6666666666666667;
gbc.weighty = 1f;
gbc.gridheight = GridBagConstraints.REMAINDER;
add(image, gbc);
gbc.gridheight = 1;
gbc.gridx++;
gbc.weightx = 0.3333333333333333f;
gbc.weighty = 0.25f;
add(button, gbc);
gbc.gridy++;
add(label, gbc);
gbc.gridy++;
add(comboBox, gbc);
gbc.gridy++;
add(otherButton, gbc);
}
}
}
This could, just as easily, be used with two JPanels
, one been for the image and one for the options. This would remove the need to use gridheight
...
Upvotes: 2