Swing - GridBagLayout 中的 JScollArea 在调整大小时折叠
Swing - JScollArea in GridBagLayout collapses when resizing
我正在编写一个 "image viewer" 应用程序,其中央区域包含图像,周围还有工具栏等。
我选择了一个 GridBagLayout 来满足我需要的灵活性,但是一旦主要 window 缩小,整个滚动窗格就会折叠成 0x0 像素的区域,而不是在图像周围出现滚动条。
请在下面找到一个最小代码来说明这一点。尝试将尺寸保留为 500x500,并通过向内拖动其中一个角将 window 缩小几个像素:
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 来 "fixed",但是较小的图像(尝试使用 50x50)不是居中了:-(
有没有办法指定:
- 如果图片小于显示区域,应该居中
- 如果图像大于显示区域,滚动窗格应填满整个显示区域
?
... but making it larger causes the scrollpane to stick at the top left
weightx/y 约束告诉 GridBayLayout 如何在框架中分配额外的 space。由于您只有一个具有非零值的组件,因此所有额外的 space 都会进入面板。所以组件定位在标签下可用的space的top/left处。
g2d.drawOval(0, 0, IMG_WIDTH, IMG_HEIGHT);
然后您的绘画代码总是在相对于面板位置的 top/left 处绘制椭圆。
如果你想让椭圆居中,那么你的绘画代码必须改变:
//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
将自动将图像置于标签可用的 space 中心。
请注意,这也是您更改框架宽度时标签文本水平居中的原因。
我正在编写一个 "image viewer" 应用程序,其中央区域包含图像,周围还有工具栏等。
我选择了一个 GridBagLayout 来满足我需要的灵活性,但是一旦主要 window 缩小,整个滚动窗格就会折叠成 0x0 像素的区域,而不是在图像周围出现滚动条。
请在下面找到一个最小代码来说明这一点。尝试将尺寸保留为 500x500,并通过向内拖动其中一个角将 window 缩小几个像素:
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 来 "fixed",但是较小的图像(尝试使用 50x50)不是居中了:-(
有没有办法指定:
- 如果图片小于显示区域,应该居中
- 如果图像大于显示区域,滚动窗格应填满整个显示区域
?
... but making it larger causes the scrollpane to stick at the top left
weightx/y 约束告诉 GridBayLayout 如何在框架中分配额外的 space。由于您只有一个具有非零值的组件,因此所有额外的 space 都会进入面板。所以组件定位在标签下可用的space的top/left处。
g2d.drawOval(0, 0, IMG_WIDTH, IMG_HEIGHT);
然后您的绘画代码总是在相对于面板位置的 top/left 处绘制椭圆。
如果你想让椭圆居中,那么你的绘画代码必须改变:
//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
将自动将图像置于标签可用的 space 中心。
请注意,这也是您更改框架宽度时标签文本水平居中的原因。