I have a medium-large UI that uses a BorderLayout; the center is a tabbed pane containing various panels with various layouts, etc.
I want the panel in the center of this border layout to resize according to the size of the window, but I don't want the components within the panel to stretch. Labels, combo boxes, text fields, buttons -- I want them to stay at their preferred sizes, and allow the panel that contains them to stretch. I put them in a scroll pane in case the space gets too small for the panel.
Various posters with colorful vocabularies warn against the danger of using any of the setXXXsize() methods on components. That's what I do now, and I'd like to learn how to avoid it.
GridBagLayout is not appropriate for some of my panels. It is, by nature, oriented around rows and columns, and not everything fits into rows and columns. Of course I could create artificial rows and columns to fit everything into, but I'm really hoping Swing has more layout options than that.
Vertical Glue doesn't do it either. I've included it in HFOE's beloved SSCE:
package example;
import java.awt.BorderLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class BorderAndBox extends JFrame
{
public static void main(String args[])
{
BorderAndBox bnb = new BorderAndBox();
bnb.createUI();
bnb.setVisible(true);
}
public void createUI()
{
JPanel borderPanel = new JPanel(new BorderLayout());
JLabel northLabel = new JLabel("Nawth");
borderPanel.add(northLabel, BorderLayout.NORTH);
String[] southComboChoices = { "one", "two", "three" };
JComboBox southCombo = new JComboBox(southComboChoices);
borderPanel.add(southCombo, BorderLayout.SOUTH);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
String[] firstChoices = { "first", "uno", "UN" };
String[] secondChoices = { "second", "dos", "zwei" };
String[] thirdChoices = { "third", "tres", "drei" };
JComboBox firstCombo = new JComboBox(firstChoices);
JComboBox secondCombo = new JComboBox(secondChoices);
JComboBox thirdCombo = new JComboBox(thirdChoices);
centerPanel.add(firstCombo);
centerPanel.add(secondCombo);
centerPanel.add(thirdCombo);
centerPanel.add(Box.createVerticalGlue()); // first attempt; does NOT
// take up available vertical space, instead it appears to create a space
// that is shared equally among the (now) four components of this space.
borderPanel.add(centerPanel, BorderLayout.CENTER);
getContentPane().add(borderPanel);
pack();
}
}
If you enlarge the window, the comboboxes in the center enlarge; as written, a vertical glue piece below them also enlarges, but doesn't take up all available space. It appears it is given as much space as each of them.
So what is a good way to approach this?
The BorderLayout is used to arrange the components in five regions: north, south, east, west, and center. Each region (area) may contain one component only.
There can only be one component in any region, so any component already in the named region is removed. To get multiple components in one region of a BorderLayout, group the components in another container, and add the container as a whole to the layout.
Note : Using BorderLayout manager, we can only add one component in a particular region. If we add more than one component in any region, only the last added component will be visible in that region.
For border layouts, the constraint must be one of the following constants: NORTH , SOUTH , EAST , WEST , or CENTER . Most applications do not call this method directly. This method is called when a component is added to a container using the Container. add method with the same argument types.
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class BorderAndBox extends JFrame
{
public static void main(String args[])
{
BorderAndBox bnb = new BorderAndBox();
bnb.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
bnb.createUI();
bnb.setVisible(true);
}
public void createUI()
{
JPanel borderPanel = new JPanel(new BorderLayout());
JLabel northLabel = new JLabel("Nawth");
borderPanel.add(northLabel, BorderLayout.NORTH);
String[] southComboChoices = { "one", "two", "three" };
JComboBox southCombo = new JComboBox(southComboChoices);
borderPanel.add(southCombo, BorderLayout.SOUTH);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
String[] firstChoices = { "first", "uno", "UN" };
String[] secondChoices = { "second", "dos", "zwei" };
String[] thirdChoices = { "third", "tres", "drei" };
JComboBox firstCombo = new JComboBox(firstChoices);
JComboBox secondCombo = new JComboBox(secondChoices);
JComboBox thirdCombo = new JComboBox(thirdChoices);
centerPanel.add(firstCombo);
centerPanel.add(secondCombo);
centerPanel.add(thirdCombo);
centerPanel.add(Box.createVerticalGlue()); // first attempt; does NOT
// take up available vertical space, instead it appears to create a space
// that is shared equally among the (now) four components of this space.
JPanel centerPanelConstrain = new JPanel(new GridBagLayout());
centerPanelConstrain.add(centerPanel);
borderPanel.add(centerPanelConstrain, BorderLayout.CENTER);
getContentPane().add(borderPanel);
pack();
}
}
See also this answer. There is more than one way to solve this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With