I'm generating some JComponents in code and using the GridBag layout to arrange them. My layout consists of 12 rows and 3 columns, with each row consisting of a JSlider, a JCheckBox and a JLabel. Here's the code I'm using to generate the UI:
final int NUM_MOTORS = 12;
// This is the panel I'm adding the components to.
pnlMotorSliders.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
for (int i = 0; i < NUM_MOTORS; ++i) {
c.gridy = i;
// Create the slider
JSlider slider = new JSlider(SwingConstants.HORIZONTAL, 10, 4085, 10);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.weightx = 0.9;
pnlMotorSliders.add(slider, c);
// Create the checkbox
JCheckBox checkBox = new JCheckBox();
checkBox.setOpaque(true);
checkBox.setBackground(Color.blue);
c.fill = GridBagConstraints.NONE;
c.gridx = 1;
c.weightx = 0.1;
pnlMotorSliders.add(checkBox, c);
// Create the current label
JLabel label = new JLabel("0");
label.setBorder(BorderFactory.createLineBorder(Color.red));
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 2;
c.weightx = 0.2;
pnlMotorSliders.add(label, c);
}
The problem I'm having is that when I set the text in any of the JLabels, they change their width and affect the rest of the layout, even if the width of the text that I'm setting appears to be much smaller than the width of the JLabel. The following two screenshots demonstrate what I mean (the red and blue borders were for debugging purposes):
I've set the text on the bottom JLabel to "-12". Even though the JLabel appears to be much wider than the text, it has changed its size, affecting the rest of the layout.
Why is this happening and what can I do to prevent it?
You can fix the size of the labels by setting the minimum, prefered and maximum size:
label.setMinimumSize(width, height);
label.setPreferedSize(width, height);
label.setMaximumSize(width, height);
Also make sure to set the GridBagConstraints#fill to NONE, although I am not sure if that is still neccessary (I think it is).
EDIT: btw, to get rid of those nasty dashed lines around the focused Component, you can just set it to be not focusable:
slider.setFocusable(false);
The set-the-preferred-size solution works only if you don't have the components horizontally fill their bag in the GridBagLayout.
Another solution is to remove the weight you have placed on components in that column of your GridBagLayout. You can then control the column width manually. An easy way to do so (at design time) is to place a JLabel in the column with zero height and the specific width you desire.
Why is this? You need to dig into how GridBagLayout works:
The GridBagLayout sizes its columns based on the space required, and then uses the weights to allocate the "left over" space so that the resulting column widths then add up to the total width of the panel. The space required for each column is computed by finding the widest of the components in that column.
The space required for each component is determined by asking it what width it would prefer. In your case, a JLabel with "0" is smaller than a JLabel with "-12" and so the column is changing size.
The left over space is allocated based on the horizontal weights assigned to components in each column. The weights are totaled and percentages for each column are determined based on that column's percent of the total.
The column size is determined based on the space required PLUS the left over space. So, if all your components in the column have no weight then you'll not get any left over space, and hence not get dynamic changes.
A third solution is to just not use GridBagLayout.
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