BoxLayout不遵守JButton的首选大小

4

我一直在开发一个小项目,旨在模拟赌博游戏。不幸的是,在处理 BoxLayout 时遇到了一些奇怪的问题。据我所知,LayoutManager 通常会遵守任何组件的首选大小。然而,在下面的代码中,BoxLayout 没有这样做。

以下是我的代码:

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



public class Main 
{
    public static void main(String[] args)
    {
      JFrame.setDefaultLookAndFeelDecorated(true);
      JFrame frame = new JFrame("Suit-Up");
      frame.setContentPane(makeGUI());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(900,450);
      frame.setLocationRelativeTo(null);
      frame.setResizable(false);
      frame.setVisible(true);
    }

    public static JPanel makeGUI()
    {
      JPanel main = new JPanel();
      main.setMinimumSize(new Dimension(900,450));
      main.setBackground(Color.red);

      JPanel infoPanel = new JPanel();
      infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.LINE_AXIS));
      infoPanel.setPreferredSize(new Dimension(900,60));
      infoPanel.setBackground(Color.green);
      main.add(infoPanel);

      JPanel infoText = new JPanel();
      infoText.setLayout(new BoxLayout(infoText, BoxLayout.PAGE_AXIS));
      infoPanel.add(infoText);

      JPanel moneyText = new JPanel();
      moneyText.setLayout(new BoxLayout(moneyText, BoxLayout.LINE_AXIS));
      infoText.add(moneyText);

      JPanel lastGameText = new JPanel();
      lastGameText.setLayout(new BoxLayout(lastGameText, BoxLayout.LINE_AXIS));
      infoText.add(lastGameText);

      JButton playAgain = new JButton("Play Again ($20)");
      playAgain.setPreferredSize(new Dimension(200,60));
      infoPanel.add(playAgain);

      JButton finish = new JButton("End Session");
      finish.setPreferredSize(new Dimension(200,60));
      infoPanel.add(finish);

      JPanel cardPanel = new JPanel();
      cardPanel.setLayout(new BoxLayout(cardPanel, BoxLayout.LINE_AXIS));
      main.add(cardPanel);

      return main;
    }
}

尽管为JButton指定了首选大小,但它们并没有改变其大小。我已经尝试使用setMaximumSize()setMinimumSize(),但都没有效果。
我是否忽略了一些明显的东西,还是这是BoxLayout的限制?

你可以始终使用 BoxLayout,但要嵌套组件... - mre
抱歉,我不确定您所说的嵌套是什么意思。我对布局管理器还比较新。 - Thrfoot
1
如果您将按钮放置在面板上,并直接将面板添加到容器中而不是按钮,则面板将被调整大小,而不是按钮。 - mre
1个回答

2
据我所知,布局管理器通常会遵循任何组件的首选大小。但实际上并非如此。首选/最小/最大大小只是布局管理器可能用来确定如何最佳布局其内容的“提示”。如果布局管理器希望,它们可以选择忽略它们。
从JavaDocs中可以看到,BoxLayout试图以组件的首选宽度(对于水平布局)或高度(对于垂直布局)来排列组件。对于水平布局,如果不是所有组件都具有相同的高度,则BoxLayout尝试使所有组件的高度与最高组件一样高。如果某个组件无法达到这个高度,那么BoxLayout将根据该组件的Y对齐方式在垂直方向上对齐该组件。默认情况下,组件的Y对齐方式为0.5,这意味着组件的垂直中心应与其他具有0.5 Y对齐方式的组件的垂直中心具有相同的Y坐标。
类似地,对于垂直布局,BoxLayout试图使列中的所有组件都与最宽的组件一样宽。如果失败,它将根据它们的X对齐方式在水平方向上对齐它们。对于PAGE_AXIS布局,水平对齐是基于组件的前沿完成的。换句话说,如果容器的ComponentOrientation从左到右,则X对齐值为0.0表示组件的左边缘,否则表示组件的右边缘。

1
我使用的首选大小不应该有任何问题。在JPanel中有足够的空间来容纳JButton,但它们拒绝通过除了向标签添加更多文本之外的任何方式修改其大小。我已经阅读了文档,但没有看到任何解释我现在遇到的问题的内容。 - Thrfoot
1
@Thrfoot 我运行了你的测试代码,无论我尝试什么,BoxLayout 都不会使用 JButtonpreferredSize。通常不建议以这种方式操纵组件的首选大小,我们通常被鼓励使用布局管理器或直接覆盖 getPreferredSize 方法。奇怪的是,FlowLayout 却完全正常... - MadProgrammer
很奇怪...好吧,我想我不能用BoxLayout使其正常工作了。你能推荐其他的布局管理器来实现一个更或多或少相似的效果吗? - Thrfoot
3
由于您将宽度和高度设置为相等,因此建议尝试使用向左对齐的 FlowLayout - MadProgrammer
1
搞定了!谢谢!我猜有时候事情就是不顺利。 - Thrfoot
答案是调用 boxLayout.invalidateLayout(container); 这将刷新它缓存的先前首选大小,从组件请求新的大小,并相应地进行调整。 - AdrianVeidt

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