如何使用GridBagLayout设置最小尺寸?

3
我有一个简单的GUI,使用了GridBagLayout,顶部是一个按钮面板,下方是一个自定义可调整大小的组件,如下图所示:

The GUI at start-up.

自定义组件(红色)的首选大小为(400, 300),最小大小为(40, 30),并且可以调整到大于该大小的任何大小。 然而,我希望我的框架尊重按钮面板的最小大小,并且不允许调整框架的大小,以使任何按钮不能完全显示在屏幕上。目前它不会这样做,因为我可以根据需要调整大小,如下所示:

The GUI resized ridiculously small.

我的当前代码如下:
import javax.swing.*;
import java.awt.*;

public class Example {
    public static void main(String[] args) {
        // Setup JFrame and GridBagLayout.
        JFrame frame = new JFrame("Example");
        Container contentPane = frame.getContentPane();
        GridBagLayout layout = new GridBagLayout();
        contentPane.setLayout(layout);
        layout.rowWeights = new double[] {0.0, 1.0};
        layout.columnWeights = new double[] {1.0};
        GridBagConstraints cons = new GridBagConstraints();

        // Add button panel with a BoxLayout.
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
        panel.add(new JButton("Button 1"));
        panel.add(new JButton("Button 2"));
        panel.add(new JButton("Button 3"));
        cons.anchor = GridBagConstraints.NORTHWEST;
        cons.gridx = 0;
        cons.gridy = 0;
        layout.setConstraints(panel, cons);
        contentPane.add(panel);

        // Add custom component, resizable.
        JComponent custom = new JComponent() {
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }

            public Dimension getMinimumSize() {
                return new Dimension(40, 30);
            }

            public void paintComponent(Graphics g) {
                g.setColor(Color.RED);
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        cons.gridx = 0;
        cons.gridy = 1;
        cons.fill = GridBagConstraints.BOTH;
        layout.setConstraints(custom, cons);
        contentPane.add(custom);

        // Pack and show frame.
        frame.pack();
        frame.setVisible(true);
    }
}

我在Mac OS X 10.8 (Java 6)和Ubuntu 3.2.8 (Java 6)上进行了测试,并观察到同样的问题。如何防止框架调整大小以覆盖任何按钮?更普遍地说,如何使GridBagLayout实际尊重组件的最小尺寸?当我打印出我的框架的最小尺寸时,我得到了(291, 81),这正是我想要的,但当我调整框架的大小时,它超过了这个值。
注意:我查看了此相关问题,但它似乎没有回答我的问题。

尝试设置框架的最小大小。 - MadProgrammer
此外,frame.getMinimumSize() 返回正确的最小大小而无需进行任何操作。然而,在调整框架大小时似乎并未强制执行此最小大小。 - DanielGibbs
我不知道为什么,但如果我使用 frame.setMinimumSize(frame.getContentPane().getMinimumSize()); 它似乎可以工作。 - MadProgrammer
有趣的是,看一下这个错误报告。设置最大和最小尺寸会导致报告的行为吗? - Java Devil
@JavaDevil 我和错误报告中的行为相同。 - DanielGibbs
显示剩余4条评论
3个回答

4

我不确定为什么,但如果我使用...

frame.setMinimumSize(frame.getMinimumSize());

UI被创建后(显然),它就可以工作了。

我“认为”这与((WindowPeer)peer).updateMinimumSize();WindowsetMinimumSize方法中有关...


太好了!正是我要找的。虽然这导致了我期望的默认行为,但这确实非常奇怪。 - DanielGibbs
1
问题(我认为)在于布局管理器根本没有应用于窗口,而是应用于内容窗格或其内容。它也可能是底层框架(对等体)的限制,即它不会探测父窗口的大小限制信息,而是使用先前应用的任何值...但这只是我的猜测。 - MadProgrammer

2
如果您的框架设置了最小尺寸,则可以向框架添加ComponentListener并实现componentResized方法。
例如:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class Test {
    public static void main(String[] args) 
    {
        final JFrame frame = new JFrame("My Frame");
        frame.setMinimumSize(new Dimension(200,200));
        frame.addComponentListener( new ComponentAdapter()
        {
            public void componentResized(ComponentEvent evt)
            {
                Dimension size = frame.getSize();
                Dimension min = frame.getMinimumSize();
                if (size.getWidth() < min.getWidth())
                {
                    frame.setSize((int)min.getWidth() ,(int) size.getHeight());
                }
                if (size.getHeight() < min.getHeight())
                {
                    frame.setSize((int)size.getWidth() ,(int) min.getHeight());
                }
            }
        });
        frame.setSize(300,300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

这是一个部分解决方案,但目前来说是最接近的。它看起来有点丑,因为你可以将框架调整得太小,但当你松开鼠标时,它会跳回到最小尺寸。理想情况下,我希望能完全防止缩小到最小尺寸以下。 - DanielGibbs

-1
我经常遇到这种关于GridBagConstraints默认值的问题:早已养成了显式地设置它们(如weightx, gridwidth等)的习惯。通常这样做可以让GridBagLayout尊重我的最小尺寸限制。如果有人知道我覆盖了哪个默认值来达到这个效果,我很好奇 :-)

不行,我尝试显式地设置所有约束的属性,但没有任何变化。 - DanielGibbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接