修复 JScrollPane 的高度

Moi*_*ira 3 java swing

我不知道我面临的问题是否仅针对我的情况,所以我写了一个精简版,说明了导致我的问题的原因(以JLabels 作为示例组件)。

public class InterestingBehavior {

    static int direction = -4;
    static final boolean useScroll = true;
    static final String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                                             + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    public static void main(String[] args) {
        JFrame test = new JFrame("Test");
        test.setSize(500, 300);
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        test.setLayout(new BoxLayout(test.getContentPane(), BoxLayout.Y_AXIS));
        for (int i = 0; i < 10; i++)
            test.add(useScroll ? new JScrollPane(new JLabel(longString)) : new JLabel(longString));
        test.add(Box.createVerticalGlue()); //should use all available space

        final int min = 300, max = 600;
        new Timer(50, e -> {
            int h = test.getHeight();
            SwingUtilities.invokeLater(() -> test.setSize(test.getWidth(), h + direction));
            direction = h == min || h == max ? -direction : direction;
        }).start();

        test.setVisible(true);
    }

}
Run Code Online (Sandbox Code Playgroud)

框架会自行调整大小以显示我想要/不想要的内容。添加JLabelsBoxLayout使它们都保持在顶部JFrame- 这就是我想要的,因为我在面板上添加了垂直胶水。但是,如果我将JLabela包裹起来JScrollPane,它会决定根据 a 的高度自动调整自身的垂直大小JFrame- 如何避免这种行为并使滚动窗格保持恒定高度?

框架:

展开的滚动窗格

当调整大小时,变成

小窗格

这不是我想要的。

如何将一维固定为与子组件(视口)完全一致?

小智 5

问题在于它JScrollPane本身会占用它获得的所有空间。BoxLayout 公平地分配 JScrollPanes 和垂直胶水之间的可用空间。

解决方案是使用例如限制 JScrollPanel 要求的垂直空间 jScrollPane.setMaxmimumSize(new Dimension(1000, 50))

现在,您让每个 ScrollPane 准确地抓取这个空间,这会导致在调整大小和实际需要绘制水平滚动条时出现奇怪的行为。因此,您可能也想要一个首选尺寸,例如jScrollPane.setPreferredSize(new Dimension(0, 50))

这里是完整的例子:

    static int direction = -4;
    static final boolean useScroll = true;
    static final String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                                             + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

    public static void main(String[] args) {
        JFrame test = new JFrame("Test");
        test.setSize(500, 300);
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        test.setLayout(new BoxLayout(test.getContentPane(), BoxLayout.Y_AXIS));
        for (int i = 0; i < 10; i++) {
            if(useScroll) {
                JScrollPane jScrollPane = new JScrollPane(new JLabel(longString));
                jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                jScrollPane.setMaximumSize(new Dimension(1000, 50));
                jScrollPane.setPreferredSize(new Dimension(0, 50));
                test.add(jScrollPane);
            } else {
                 test.add(new JLabel(longString));
            }
        }
        test.add(Box.createVerticalGlue()); //should use all available space

        final int min = 300, max = 600;
        new Timer(50, e -> {
            int h = test.getHeight();
            SwingUtilities.invokeLater(() -> test.setSize(test.getWidth(), h + direction));
            direction = h == min || h == max ? -direction : direction;
        }).start();

        test.setVisible(true);
    }
Run Code Online (Sandbox Code Playgroud)