如何获取JScrollPane以填充所有剩余的可用空间

时间:2016-08-18 13:50:44

标签: java swing

我对Swing很新。我有一个应用程序,可以根据外部输入动态生成UI。在面板的顶部,有一个带有一些标题文本的JLabel,然后是一个按钮(告诉应用程序重新加载动态生成的东西),然后在下面是一个包含所有动态生成的东西的JScrollPane。我希望标签和按钮只占用所需的垂直空间,然后滚动窗格以填充所有剩余的可用空间。

我使用GridBagLayout,并在添加滚动窗格之前设置gbc.fill = BOTH。

我已经整理了一个SSCCE,当它第一次加载时,窗口看起来就像我想要的那样。但是,如果我将窗口调整得更小,我的期望是滚动窗格将继续消耗所有可用空间,并且会出现滚动条。但恰巧的是,只要我将窗口缩小甚至一个像素,滚动窗格就会变得很小,其内容几乎不可见。

我找到了How to get a JScrollPane to resize with its parent JPanel,但是当JScrollPane不是独生子女时,这并不起作用。可以这么说。

我做错了什么?

SSCCE:

public class SwingTest {
    public static void main(String[] args) {
        JPanel bigPanel = new JPanel();
        bigPanel.setLayout(new GridLayout(10, 10));
        for (int i = 0; i < 100; i++) {
            bigPanel.add(new JCheckBox("Item " + i));
        }

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;

        JFrame mainWindow = new JFrame("Swing Test");
        mainWindow.setLayout(new GridBagLayout());
        mainWindow.add(new JLabel("Heading"), gbc);
        mainWindow.add(new JButton("Button"), gbc);
        gbc.fill = GridBagConstraints.BOTH;
        mainWindow.add(new JScrollPane(bigPanel), gbc);

        mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        mainWindow.setLocationByPlatform(true);
        mainWindow.pack();
        mainWindow.setVisible(true);
    }
}

1 个答案:

答案 0 :(得分:0)

所以,我在写SSCCE时想到了这一点。 (有趣的是如何发生!)

根据我链接的相关问题,我尝试使用BorderLayout:

public class SwingTest {
    public static void main(String[] args) {
        JFrame mainWindow = new JFrame("Swing Test");

        mainWindow.setLayout(new BorderLayout());
        mainWindow.add(new JLabel("Heading"));
        mainWindow.add(new JButton("Button"));
        JPanel bigPanel = new JPanel();
        bigPanel.setLayout(new GridLayout(10, 10));
        for (int i = 0; i < 100; i++) {
            bigPanel.add(new JCheckBox("Item " + i));
        }
        mainWindow.add(new JScrollPane(bigPanel));

        mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        mainWindow.setLocationByPlatform(true);
        mainWindow.pack();
        mainWindow.setVisible(true);
    }
}

但那不起作用,因为我认为我对BorderLayout的作用有一个根本的误解。通过不对我的add(...)调用指定约束,我将所有三个组件添加到&#34; CENTER&#34;窗格。 BorderLayout的目的是容纳一个随容器大小缩放的单个组件,并且您可以将其他东西放在边缘(即边框)上,这些东西将保持固定大小。每个位置只能有一个组件,所以通过将所有三个组件添加到CENTER,我只剩下我添加的最后一个组件。我需要将我的标题和按钮包装在JPanel中并将其放在顶部边缘:

public class SwingTest {
    public static void main(String[] args) {
        JPanel top = new JPanel();
        top.setLayout(new BoxLayout(top, BoxLayout.PAGE_AXIS));
        top.add(new JLabel("Heading"));
        top.add(new JButton("Button"));

        JPanel bigPanel = new JPanel(new GridLayout(10, 10));
        for (int i = 0; i < 100; i++) {
            bigPanel.add(new JCheckBox("Item " + i));
        }

        JFrame mainWindow = new JFrame("Swing Test");
        mainWindow.setLayout(new BorderLayout());
        mainWindow.add(top, PAGE_START);
        mainWindow.add(new JScrollPane(bigPanel), CENTER);

        mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        mainWindow.setLocationByPlatform(true);
        mainWindow.pack();
        mainWindow.setVisible(true);
    }
}

之后组件的行为正确,但是当窗口变得足够大以至于不需要滚动时,复选框的网格会扩展以适应空间,这是我不想要的。我只是想把它钉在左上角。以下是解决问题的原因:

public class SwingTest {
    public static void main(String[] args) {
        JPanel top = new JPanel();
        top.setLayout(new BoxLayout(top, BoxLayout.PAGE_AXIS));
        top.add(new JLabel("Heading"));
        top.add(new JButton("Button"));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = NONE;
        JPanel bigPanel = new JPanel(new GridBagLayout());
        for (int i = 0; i < 10; i++) {
            gbc.gridx = RELATIVE;
            gbc.gridy = i;
            gbc.anchor = NORTHWEST;
            for (int j = 0; j < 10; j++) {
                bigPanel.add(new JCheckBox("Item " + (10 * i + j)), gbc);
            }
        }

        // add a panel to the right side to prevent the grid from growing horizontally
        gbc.fill = BOTH;
        gbc.weightx = 1;
        bigPanel.add(new JPanel(), gbc);

        // add another panel to the bottom to prevent the grid from growing vertically
        gbc.gridy = RELATIVE;
        gbc.gridx = 0;
        gbc.weightx = 0;
        gbc.weighty = 1;
        bigPanel.add(new JPanel(), gbc);

        JFrame mainWindow = new JFrame("Swing Test");
        mainWindow.setLayout(new BorderLayout());
        mainWindow.add(top, PAGE_START);
        mainWindow.add(new JScrollPane(bigPanel), CENTER);

        mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        mainWindow.setLocationByPlatform(true);
        mainWindow.pack();
        mainWindow.setVisible(true);
    }
}

外卖:

  • 始终将JScrollPane放在BorderLayout的CENTER中。
  • 如果您不希望类似网格的内容扩展其细胞填充&#34;调整大小时动态,使用GridBagLayout,而不是GridLayout。