GridBagLayout 中的 JScrollPane 影响应用程序的大小

JScrollPane in GridBagLayout affecting size of application

我一直在练习 Java GUI 开发,在我的一个项目中,我使用了带有各种控件的 GridBagLayout,例如 JLabelJComboBoxeJTable 包裹在 JScrollPane.

但是,我注意到 JScrollPane 似乎会影响我的 JPanel,除非我的身高达到一定数量(522 像素 或更高到 .Pack()) 我的 JComboBoxe 似乎 "compact" 并且宽度将被设置为适合文本而不是我指定的大小 (200 px) .

所以我的问题是造成这种情况的原因是什么以及我该如何解决它以便 JFrame 的高度可以更小而不会导致我的 JComboBoxe 表现得那样。

我的应用程序的屏幕截图before/after 调整大小:

我的申请的当前代码:

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();
    }

}

编辑:我通过为每个 JComboBox 设置最小尺寸来解决高度问题,但是从 .pack() 生成的白色 space 仍然没有修复。我还注意到,如果我垂直调整 window 的大小并使其变小,table 的宽度似乎会减少一个像素。也许这与它有关?

这可能是因为 Scollpane 试图填满整个 space。 setPrefferedSize 集,正如您可能从其名称中注意到的那样,不是严格的大小。方法 setMaximumSizesetMinimumSize 设置了严格的限制(事实上不是,但差不多:))。此后,添加这两行代码:

cmbTeam.setMinimumSize(new Dimension(200,25));
cmbPosition.setMinimumSize(new Dimension(200,25));

what is causing this and

通常,当没有足够的 space 来在 GridbagLayout 中以其首选大小显示组件时,组件将对齐到其最小大小。我不确定为什么更改高度会导致首选宽度发生变化,但不知何故这会导致组合框以最小宽度显示。

how would I fix it so the JFrame's height can be smaller without causing my JComboBoxes to behave like that.

利用框架的默认 BorderLayout。将您的组件单独添加到框架中:

//frame.add(panel);
frame.add(panel, BorderLayout.NORTH);
frame.add(new JScrollPane(table));
frame.add(lblResults, BorderLayout.SOUTH);

当然,您需要整理其余代码,因为您不再向面板添加滚动窗格和标签。

当宽度减小时,您仍然会看到组合框缩小。

编辑:

but that whitespace that's generated from .pack() is still not fixed.

JTable 具有 "viewport" 的硬编码首选大小。您可以通过执行以下操作来覆盖它:

table.setPreferredScrollableViewportSize(table.getPreferredSize());

正如 camickr 所说,只要没有足够的空间容纳每个组件的首选尺寸,GridBagLayout 就会将所有组件恢复为最小尺寸。

一个简单的解决方案是使最小尺寸与首选尺寸相同:

// Make sure these lines come AFTER you've set the preferred sizes.
cmbTeam.setMinimumSize(cmbTeam.getPreferredSize());
cmbPosition.setMinimumSize(cmbPosition.getPreferredSize());