I've been practicing Java GUI development and on one of my projects I'm using a GridBagLayout
with various controls such as JLabel
, JComboBoxe
, and a JTable
encased in a JScrollPane
.
However, I've noticed the JScrollPane
seems to affect my JPanel
where unless my height is a certain amount (522 px or greater according to .Pack()
) my JComboBoxe
seem to "compact" and the width will be set to fit the text instead of the size I specified (200 px).
So my question is what is causing this and how would I fix it so the JFrame
's height can be smaller without causing my JComboBoxe
s to behave like that.
Screenshot of what my app looks like before/after resize:
Current code for my application:
package gui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingConstants;
public class MainWindow {
public static void main(String[] args) {
MainWindow main = new MainWindow();
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JComboBox<String> cmbTeam, cmbPosition;
JLabel lblTeam, lblPosition, lblResults;
JTable table;
JSeparator sep1,sep2;
int rowCount;
GridBagConstraints gbc = new GridBagConstraints();
panel.setLayout(new GridBagLayout());
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1;
gbc.gridx = 0;
gbc.gridy = 0;
lblTeam = new JLabel("First Label");
panel.add(lblTeam, gbc);
gbc.gridx = 1;
lblPosition = new JLabel("Second Label");
panel.add(lblPosition, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
cmbTeam = new JComboBox<>(new String[]{"Data1","Data2","Data3"});
cmbTeam.setPreferredSize(new Dimension(200,25));
panel.add(cmbTeam, gbc);
gbc.gridx = 1;
cmbPosition = new JComboBox<>(new String[]{"Data1","Data2","Data3"});
cmbPosition.setPreferredSize(new Dimension(200,25));
panel.add(cmbPosition, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
sep1 = new JSeparator(SwingConstants.HORIZONTAL);
panel.add(sep1,gbc);
gbc.gridy = 3;
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 1;
table = new JTable(new String[][]{{"AA","AB","AC"},{"BA","BB","BC"},{"CA","CB","CC"}}, new String[]{"Col1","Col2","Col3"});
table.setFillsViewportHeight(true);
panel.add(new JScrollPane(table),gbc);
gbc.gridy = 4;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
sep2 = new JSeparator(SwingConstants.HORIZONTAL);
panel.add(sep2,gbc);
rowCount = table.getRowCount();
lblResults = new JLabel(rowCount + " results found.");
gbc.gridy = 5;
panel.add(lblResults, gbc);
frame.setTitle("GridBagLayout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(panel);
frame.pack();
}
}
EDIT: I fixed the height issue by setting a minimum dimension for each JComboBox
, but that white space that's generated from .pack()
is still not fixed. I also noticed if I resize the window vertically and make it smaller the table's width seems to decrease by a single pizel. Maybe that has something to do with it?
what is causing this and
In general, when there is not enough space to display a component at its preferred size in a GridbagLayout the component will snap to its minimum size. I'm not sure why changing the height is causing the preferred width to change but somehow this is resulting in the combo boxes being displayed at their minimum width.
how would I fix it so the JFrame's height can be smaller without causing my JComboBoxes to behave like that.
Take advantage of the default BorderLayout
of the frame. Add your components separately to the frame:
//frame.add(panel);
frame.add(panel, BorderLayout.NORTH);
frame.add(new JScrollPane(table));
frame.add(lblResults, BorderLayout.SOUTH);
Of course you will need to tidy up the rest of the code since you no longer add the scrollpane and label to the panel.
You will still see the combo boxes shrink when the width is decreased.
Edit:
but that whitespace that's generated from .pack() is still not fixed.
JTable has a hardcoded preferred size for the "viewport". You can override this by doing something like:
table.setPreferredScrollableViewportSize(table.getPreferredSize());