如何让GridBagLayout尊重按钮或面板的最小尺寸?

在下面的GridBagLayout代码中,我希望在调整JFrame的大小以使其更小时,可以遵守指定的JButton btn2的最小大小。 但是当我使JFrame变小时,btn2会小于其最小尺寸然后消失。

有人能指出我正在做错的方向吗? 也许我必须设置包含按钮的JPanel的最小大小?

任何帮助表示赞赏,谢谢!

JFrame frame = new JFrame(); frame.setSize(400,300); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(); panel.setMinimumSize(new Dimension(400,300)); panel.setBackground(Color.RED); panel.setLayout(new GridBagLayout()); GridBagConstraints gbc = null; JButton btn1 = new JButton("btn1"); btn1.setPreferredSize(new Dimension(150,50)); btn1.setMinimumSize(new Dimension(150,50)); gbc = new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0); panel.add(btn1, gbc); JButton btn2 = new JButton("btn2"); btn2.setPreferredSize(new Dimension(150,150)); btn2.setMinimumSize(new Dimension(150,150)); gbc = new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,100,100), 0, 0); panel.add(btn2, gbc); frame.getContentPane().add(panel); frame.setVisible(true); 

也许我必须设置包含按钮的JPanel的最小大小?

AFAIR GBL因忽略尺寸提示而臭名昭着。 不,这是一个纠正。 要在GBL中合理调整组件大小,请使用具有适当值的GridBagConstraints 。 但要注意,布局的行为不会显示任何将被强制小于其最小大小的组件。

我会pack()框架,然后在框架上设置最小尺寸。 以下是它的外观,将最后一行更改为..

 frame.pack(); frame.setVisible(true); frame.setMinimumSize(frame.getSize()); 

考虑到布局,我倾向于将btn1放入面板的BorderLayoutPAGE_START中,然后将其添加到另一个BL的LINE_START中。 btn2将进入外部BL的CENTER

除了安德鲁汤普森的回答:

  • 如果组件的首选尺寸能够并且将得到尊重,则GBL不会尊重组件上设置的最小尺寸。
  • 当组件的首选尺寸不能被遵守时,GBL DOES尊重组件上设置的最小尺寸,即:组件优选尺寸(w,h)但GBL认为由于空间不足而不可能,因此它会回落到广告组件的最小尺寸上。

因此,当您缩小包含框架的尺寸时,很可能使您的组件突然变大。 您只需要在其上设置一个大于首选大小的最小大小。 因此,您正在缩小框架,突然您的组件变得更大。 那是……奇怪但可能:)所有冰雹GBL。

下面是一个实现此行为的面板示例(GBC比原始GridBagConstraints更容易使用):

 private static JPanel getPanel() { JPanel panel = new JPanel(new GridBagLayout()); final JTextField textField = new JTextField("test"); final String text = "text"; final JLabel label = new JLabel(text); final JButton button = new JButton(new AbstractAction("Enlarge label!") { private String actText = text; @Override public void actionPerformed(ActionEvent arg0) { actText = actText + text; label.setText(actText); } }); GBC g; g = new GBC().locate(0, 0).weight(0.0, 0.0).align(GBC.WEST, GBC.HORIZONTAL, null); textField.setMinimumSize(new Dimension(200,20)); panel.add(textField, g); g = new GBC().locate(1, 0).weight(1.0, 0.0); panel.add(label, g); g = new GBC().locate(0, 1).weight(1.0, 1.0).span(2, 1); panel.add(button, g); return panel; } 

一般来说,我会说不使用必须在GBL内修改大小的组件。 用不同的布局管理器将其包裹在其他面板中。

如果您确实想在GBL中使用固定大小的组件,请覆盖其getPreferredSize()方法并返回所需的大小。 但我更愿意忽略这些方法。