【问题标题】:Java Swing BoxLayout layout of outer panel changes when I specify layout of inner panel当我指定内面板的布局时,外面板的 Java Swing BoxLayout 布局发生变化
【发布时间】:2021-09-29 21:29:19
【问题描述】:

我对 Java Swing 很陌生。我在包含 2 个内部面板的“外部”面板上使用 y 轴 BoxLayout。在这里你可以看到这个基本代码,2个内面板获得了盒子布局中可用高度的相等份额(第一个内面板黄色,第二个内面板橙色)

// main test frame
public class MainFrame extends JFrame {
    
    public MainFrame()
    {
        
        this.setSize(500, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.setLayout(new GridLayout(1,1));

        // outer panel: groupWrapPanel with BoxLayout
        JPanel groupWrapPanel = new JPanel();
        groupWrapPanel.setBackground(Color.blue);
        
        groupWrapPanel.setLayout(new BoxLayout(groupWrapPanel, BoxLayout.Y_AXIS));
        
        // inner panel 1: headerPanel (yellow)
        JPanel headerPanel = new JPanel();
        headerPanel.setBackground(Color.yellow);
        groupWrapPanel.add(headerPanel);
        
        // inner panel 2: headerNotesWrap (orange)
        JPanel headerNotesWrap = new JPanel();
        headerNotesWrap.setBackground(Color.orange);
        groupWrapPanel.add(headerNotesWrap);
        

        this.add(groupWrapPanel);
        this.setVisible(true);
    }
    
}

但是当我将单独的布局管理器添加到其中一个内部面板时,外部面板的布局会发生变化,并且 2 个内部面板不再获得外部面板高度的均等份额。我可以通过添加一行代码来做到这一点:

 headerPanel.setLayout(new BorderLayout());
    

谁能解释一下为什么当我为内面板指定布局管理器时外面板的布局会发生变化,以及如何防止这种情况发生。

谢谢。

编辑

这是一个相关问题,是对某人发表的评论的回应。

“BoxLayout 将确定每个组件的首选大小。如果有额外空间可用,它将平均分配空间,直到每个组件的最大大小。这可以解释为什么每个面板在第一个是 50/50情况。”

如果是这样,如果我将 2 个内部组件从面板更改为标签,为什么它们不再拉伸以填充外部面板内部的可用空间?像这样:

公共类 MainFrame 扩展 JFrame {

public MainFrame()
{
    
    // we're going to create what shall be known as a "Group Box",
    // which groups things together
    this.setSize(500, 500);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    this.setLayout(new GridLayout(1,1));

    // outer panel: groupWrapPanel with BoxLayout
    JPanel groupWrapPanel = new JPanel();
    groupWrapPanel.setBackground(Color.blue);
    
    groupWrapPanel.setLayout(new BoxLayout(groupWrapPanel, BoxLayout.Y_AXIS));
    
    // inner label 1
    JLabel label1 = new JLabel("Label 1");
    label1.setBackground(Color.yellow);
    label1.setOpaque(true);
    groupWrapPanel.add(label1);
    
    // inner label 2
    JLabel label2 = new JLabel("Label 2");
    label2.setBackground(Color.orange);
    label2.setOpaque(true);
    groupWrapPanel.add(label2);
    
    this.add(groupWrapPanel);

    
    this.setVisible(true);
}

}

再次感谢

【问题讨论】:

  • BoxLayout 将确定每个组件的首选大小。如果有额外的可用空间,它将平均分配空间,直到每个组件的最大大小。这可以解释为什么在第一种情况下每个面板都是 50/50。我不知道为什么设置布局管理器会影响布局。也许一个面板的最大尺寸会受到影响?无论如何,我们不知道您的实际要求是什么。如果您的要求是将面板保持在 50/50,请使用 GridLayout。
  • @camickr 感谢您的回复。我的要求是了解为什么会发生这种情况。我需要一个 BoxLayout,我可以在其中将面板放在“堆栈”中并了解它们的尺寸是如何计算的。如您所见,我需要能够为堆栈中的每个面板指定布局管理器。如果这意外更改了父容器的布局,则会导致问题。 50/50 不起作用堆栈中每个内部面板的高度需要由每个内部面板内的组件使用指定的布局管理器确定。
  • 如果您想要完全控制,您可以覆盖面板的getMaximumSize() 方法以返回preferred size。那么当有额外空间时,面板将不会增长。您还可以使用 GridBagLayout 来“堆叠”面板。我给了你一个建议。您是否使用不同的布局管理器验证了每个面板的首选/最大尺寸?那就是 FlowLayout 和 BorderLayout 计算的值不同吗?我猜 BorderLayout 的最大尺寸更大。
  • 在我为内部面板 1 指定布局管理器之前,这些是 2 个内部面板的尺寸: pref inner1=java.awt.Dimension[width=10,height=10] min inner1=java.awt .Dimension[width=10,height=10] max inner1=java.awt.Dimension[width=32767,height=32767] pref inner2=java.awt.Dimension[width=10,height=10] min inner2=java. awt.Dimension[width=10,height=10] max inner2=java.awt.Dimension[width=32767,height=32767]
  • 这些是我为内部面板 1 指定布局管理器后 2 个内部面板的尺寸:pref=java.awt.Dimension[width=0,height=0] min=java.awt.Dimension [width=0,height=0] max=java.awt.Dimension[width=2147483647,height=2147483647] pref=java.awt.Dimension[width=10,height=10] min=java.awt.Dimension[width =10,height=10] max=java.awt.Dimension[width=32767,height=32767]。不知道这里发生了什么

标签: java swing layout-manager border-layout boxlayout


【解决方案1】:

我在您的代码中添加了以下内容:

    setVisible(true);
    System.out.println(headerPanel.getPreferredSize());
    System.out.println(headerPanel.getMaximumSize());
    System.out.println(headerNotesWrap.getPreferredSize());
    System.out.println(headerNotesWrap.getMaximumSize());

并在使用 BorderLayout 时得到以下输出:

java.awt.Dimension[width=0,height=0]
java.awt.Dimension[width=2147483647,height=2147483647]
java.awt.Dimension[width=10,height=10]
java.awt.Dimension[width=32767,height=32767]

可以看到BorderLayout最大尺寸比FlowLayout大很多。

因此,当按比例分配额外空间时,BorderLayout 面板会得到更多。

一些可能的解决方案:

  1. 覆盖使用 BorderLayout 的面板的 getMaximumSize() 方法以返回适当的值。

  2. 使用 GridBagLayout。您还可以将面板堆叠在一列中。

  3. 尝试使用Relative Layout,它的功能类似于 BoxLayout 并且只是堆叠面板。

【讨论】:

  • 嗯,好的。在上面的 cmets 中,我做了同样的测试并注意到了差异。我想主要问题是我不明白首选、最小和最大尺寸是如何结合起来确定布局的。我绝对可以重写 getMaximumSize 来限制每个容器的大小,我只是想知道为什么首先存在这个问题。对于BoxLayout,我的理解是,它首先会根据getMinimumSize为每个组件设置一个最小尺寸,然后根据每个组件的getMaxSize相对尺寸分配额外的空间。 getPreferredSize 是从哪里来的?谢谢
  • 不,我已经说过它使用首选尺寸(不是最小尺寸)作为起点。如果你缩小框架的大小,最小尺寸就会出现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2011-02-07
  • 2017-11-23
  • 2013-11-26
  • 2022-01-19
  • 2012-09-04
相关资源
最近更新 更多