Swing - GridBagLayout中的JScollArea在调整大小时折叠。

问题描述 投票:0回答:1

我正在编写一个 "图像查看器 "应用,中心区域包含图像,加上周围的工具栏等。

我选择了GridBagLayout来满足我的灵活性需求,但是一旦主窗口缩小,图像周围没有出现滚动条,而是整个滚动条折叠成一个0x0px的区域。

请在下面找到一个最小的代码来说明这个问题。试着将尺寸保持在500x500,并通过向内拖动窗口的一个角来减少几个像素。

import javax.swing.*;
import java.awt.*;

public class ScrollTest3 {

    private static final int IMG_WIDTH = 500; // 50 or 500 or 2000
    private static final int IMG_HEIGHT = 500; // 50 or 500 or 2000

    private static GridBagConstraints getScrollPaneConstraints() {
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 1;
        c.weightx = 1;
        c.weighty = 1;

        // With the next line, shrinking the window makes scrollbars appear ok,
        // ... but making it larger causes the scrollpane to stick at the top left
        // Without the next line, enlarging the window keeps image centered,
        // ... but making it smaller causes the scrollpane to collapse

        //c.fill = GridBagConstraints.BOTH;

        return c;
    }

    public static void addComponentsToPane(Container container) {
        container.setLayout(new GridBagLayout());

        // Add top bar
        container.add(new JLabel("This would be a top bar with information"), new GridBagConstraints());

        // Prepare main image panel
        JPanel imagePanel = new JPanel() {
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                // Image replaced by a shape for demonstration purpose
                g2d.drawOval(0, 0, IMG_WIDTH, IMG_HEIGHT);
            }

            public Dimension getMinimumSize() {
                return new Dimension(IMG_WIDTH, IMG_HEIGHT);
            }

            public Dimension getPreferredSize() {
                return new Dimension(IMG_WIDTH, IMG_HEIGHT);
            }

            public Dimension getMaximumSize() {
                return new Dimension(IMG_WIDTH, IMG_HEIGHT);
            }
        };
        JScrollPane scrollableImagePanel = new JScrollPane(imagePanel);

        container.add(scrollableImagePanel, getScrollPaneConstraints());
    }

    private static void limitAppSize(JFrame frame) {
        frame.pack();

        Dimension preferred = frame.getSize();
        GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
        Rectangle bounds = env.getMaximumWindowBounds();

        preferred.width = Math.min(preferred.width, bounds.width);
        preferred.height = Math.min(preferred.height, bounds.height);

        frame.setSize(preferred);
    }


    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ScrollTest3");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addComponentsToPane(frame.getContentPane());
        limitAppSize(frame);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }
}

正如你在注释中看到的,可以通过指定GridBagConstraints.BOTH来 "固定""填充 "字段,但是较小的图片(尝试50x50)不再居中了 :-(

有没有一种方法可以指定。

  • 如果图像比显示区域小,它应该居中。
  • 如果图像大于显示区域,滚动窗格应填满整个显示区域。

?

java swing window jscrollpane gridbaglayout
1个回答
1
投票

......但把它变大就会导致滚动条粘在左上角。

weightxy约束告诉GridBayLayout如何在框架中分配额外的空间。由于你只有一个非零值的组件,所有的额外空间都会被分配给面板。所以组件被定位在标签下可用空间的左上方。

g2d.drawOval(0, 0, IMG_WIDTH, IMG_HEIGHT);

那么你的绘制代码总是在相对于面板位置的顶部左上角绘制椭圆。

如果你想让椭圆居中,那么你的绘制代码必须改变。

//g2d.drawOval(0, 0, IMG_WIDTH, IMG_HEIGHT);
int x = (getWidth() - IMG_WIDTH) / 2;
int y = (getHeight() - IMG_HEIGHT) / 2;
g2d.drawOval(x, y, IMG_WIDTH, IMG_HEIGHT);

我正在写一个 "图像查看器 "的应用程序 有一个包含图像的中心区域。

然而,正如您上一个问题的评论中所建议的那样,最简单的解决方案是只用一个 JLabel 来显示图像。该 JLabel 将会在标签的可用空间内自动将图像居中。

请注意,这也是为什么当您改变框架的宽度时,标签文本会水平居中的原因。

© www.soinside.com 2019 - 2024. All rights reserved.