摇摆-调整大小时GridBagLayout中的JScollArea折叠 [英] Swing - JScollArea in GridBagLayout collapses when resizing

查看:100
本文介绍了摇摆-调整大小时GridBagLayout中的JScollArea折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个图像查看器"应用程序,该应用程序的中心区域包含图像以及周围的工具栏等.

I'm writing an "image viewer" app with a central area containing the image, plus toolbars etc. around it.

我选择了GridBagLayout来获得所需的灵活性,但是一旦缩小主窗口,整个滚动窗格就会塌陷到0x0px区域,而不是在图像周围出现滚动条.

I selected a GridBagLayout for the flexibility I need, but as soon as the main window is reduced, instead of having scrollbars appearing around the image, the whole scrollpane collapses to a 0x0px area.

请在下面找到一个最小的代码来说明这一点.尝试将尺寸保留为500x500,并通过向内拖动一个角将窗口缩小几个像素:

Please find below a minimal code to illustrate this. Try leaving the dimensions at 500x500 and reducing the window by a few pixels by dragging one of its corners inwards:

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

您可以在注释行中看到,可以通过为"fill"字段指定GridBagConstraints.BOTH来对其进行修复",但是较小的图像(尝试使用50x50)不再居中:-(

As you can see in the commented out line, it can be "fixed" by specifying GridBagConstraints.BOTH for the "fill" field, but then smaller images (try with 50x50) are not centered anymore :-(

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

Is there a way to specify that:

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

?

推荐答案

...但是将其放大会导致滚动面板停留在左上方

... but making it larger causes the scrollpane to stick at the top left

weightx/y约束告诉GridBayLayout如何在框架中分配额外的空间.由于您只有一个具有非零值的组件,因此所有多余的空间都将分配给面板.因此,该组件位于标签下方可用空间的顶部/左侧.

The weightx/y constraints tells the GridBayLayout how to allocate extra space in the frame. Since you only have a single component with non-zero values all the extra space goes to the panel. So the component is positioned at the top/left of the space available under the label.

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

然后您的绘画代码总是在相对于面板位置的顶部/左侧绘制椭圆形.

Then your painting code always paints the oval at the top/left relative to the panels location.

如果要使椭圆居中,则您的绘画代码必须更改:

If you want the oval centered, then your painting code must change:

//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);

我正在编写一个图像查看器"应用,其中心区域包含图像

I'm writing an "image viewer" app with a central area containing the image

但是,正如您在上一个问题的评论中所建议的那样,最简单的解决方案是仅使用JLabel来显示图像. JLabel会将图像自动居中放置在标签可用的空间中.

However, as was suggested in the comments of your last question, the easiest solution is to just use a JLabel to display the image. The JLabel will automatically center the image in the space available to the label.

请注意,这也是在更改框架宽度时标签文本水平居中的原因.

Note, this is also why your label text is centered horizontally as you change the width of the frame.

这篇关于摇摆-调整大小时GridBagLayout中的JScollArea折叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆