JPanel中的固定宽度、可变高度与流布局

7
我在使用Java的布局管理器时遇到了一个烦人的问题。我有以下情况:在一个面板A中,有两个其他的面板B和C,B面板采用绝对布局,C面板采用FlowLayout布局。B面板高度定制且通过setPreferredSize设置了固定大小。C面板应该具有与B面板相同的固定宽度,但是除此之外,其高度应该根据流中添加的组件数量而变化。最终的A面板应该具有固定的宽度和A.height + B.height作为高度 - 至少这就是我想要的。
然而,我得到的结果是面板A的宽度根本不固定(即使我设置了其首选大小),并且面板C中的内容没有自动换行,而是显示在一行中。当然,这也导致B面板的宽度比它应该的大。
我该怎么办才能解决这个问题?是否有更好的布局,还是我必须使用绝对布局来模拟所有内容?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Test extends JPanel
{
    public Test ()
    {
        this.setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );

        JPanel top = new JPanel( null );
        top.setBackground( Color.GREEN );
        top.setPreferredSize( new Dimension( 200, 20 ) );
        JPanel flowPanel = new JPanel( new FlowLayout( FlowLayout.LEFT, 2, 2 ) );

        this.add( top );
        this.add( flowPanel );

        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
    }
}
4个回答

10

这真的很有效!如果没有人提出本地解决方案,那么这就是我要采用的。谢谢!只是太糟糕了,标准布局管理器在如此常见(至少对我来说)的情况下总是失败,你总是最终需要一个新的自定义布局管理器.. :/ - poke
@poke:对我来说,这代表了一种选择偏见——我倾向于忘记标准布局通常只是起作用!WrapLayout也是编写自己的管理器的一个很好的例子。 - trashgod

0

放置在边界布局(BorderLayout)的LINE_END或LINE_START部分的所有物件都将保持其宽度不变: 只有高度会根据容器大小进行调整

NORTH和SOUTH的宽度可变

CENTER的宽度和高度可变

LINE_START和LINE_END只有高度可变

因此,我建议您将'C'容器放置在这种类型的BorderLayout区域中


0
提供您所需的高级视图配置的最佳方法是通过将您的FlowLayout替换为强大的GridBagLayoutManager。值得注意的是,通常由GridBagConstraints表示的约束条件在使用流畅的子类(如GBC)时更容易理解。
最后,像往常一样,您应该考虑查看Swing教程

嗯,感谢提供链接(尤其是GBC ^^),但我不确定如何使用GridBagLayout复制FlowLayout给我的效果。实际上,我想将那些由于父JPanel的固定宽度而没有足够空间的组件(这里是按钮)包装到下一行中。 - poke

0
  1. 不应该直接将子元素添加到框架中。始终添加到 contentPane -> this.getContentPage().add(...)

  2. 为使您的布局正常工作,请在内容页中放置一个带有 GridBagLayout 的 JPanel,并使该面板填充内容页。

  3. 给 GridBagLayout 设置 2 列。

现在,您无法禁用窗口的水平调整大小,因此必须找到另一种处理额外空间的方法。我建议给第一列设置固定宽度(设置 fill=NONE),并让面板 C 填充剩余空间。

如果将面板 B 的所有尺寸(最小、最大、首选)设置为首选尺寸,则其大小不应再更改。

提示:如果 Swing 布局不起作用,请将其嵌套在另一个布局中。


1
关于第一点:“为了方便起见,add及其变体,removesetLayout已被重写以必要时转发到contentPane。”http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html - trashgod
请注意,我不是在框架/窗口内工作,而是我的实际类别是一个JPanel本身。它是我的描述中的面板A,并且在不同的布局中使用,该布局不会改变其大小。 - poke
@trashgod:那是从Java 6开始的。 - Aaron Digulla
@poke:啊,那就给面板 A 设定一个 GridBagLayout 布局,2 列,同样的宽度(给它们相同的权重)。 - Aaron Digulla
1
转发方便功能出现在Java 5中,约为2004年。http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/JFrame.html - trashgod

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