GridBagLayout 中的 JPanel 不保持比例(weightx)

JPanel in GridBagLayout does not keep proportion (weightx)

我有以下情况。我用 GridBagLayout 创建了一个具有以下比例的 JPanel。我想弄清楚这一点,然后我将添加更多组件。现在我有类似

的东西
------------------------------------
|LABEL 45%  | LABEL 10% | LABEL 45%|
------------------------------------

每个标签水平和垂直各占 1 个单元格 (gridwidth/height = 1)

权重 (x) 分别为 0.45、0.1 和 0.45(从左到右)

权重 (y) 为 0.0

所有标签都已填充 GBC.HORIZONTAL,锚点为 WES​​T、WEST、EAST。

JPanel topPanel = new JPanel(new GridBagLayout());

    topPanel.add(new JLabel("1"), new GridBagConstraints(
        0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));
    topPanel.add(new JLabel("2"), new GridBagConstraints(
        1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.BOTH, INSETS_0PX, 0, 0));
    topPanel.add(new JLabel("3"), new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));

此时一切正常,第一个标签获得与右侧标签完全相同的 space(可用宽度的 45%,另一个获得 10%)。完美。

但是当我尝试添加另一个带有 GridBagLayout 的 JPanel 而不是标签(left/right)时,比例没有保持定义。

在左边我想添加一个JPanel,定义如下

----------------------
|JLabel..............|
|--------------------|
|JTextArea...........|
|....................|
----------------------

JLabel 的权重为 0.0(对于 x/y)、WEST 锚点和填充 NONE

JTextArea - 权重 1.0(x),1.0,WEST 锚点,填充两者(以便拉伸)

myPanel = new JPanel(new GridBagLayout());
myPanel.add(new JLabel("TITLE", new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
myPanel.add(new JTextArea(5,25), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
        GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));

在右侧,我想添加一个带有 GridBagLayout 的 JPanel,它包含另外两个带有 GridBagLaouts 的 JPanel(现在描述如何定义没有意义)。

--> 因此,当我添加左侧面板而不是标签时,它占据了大约 60% 的屏幕(这不对,它应该占 45%)。

你能找出问题所在吗?我没主意了

LE:这是一个简单的例子

public class Example extends JFrame {

public Example() {
    init();
}

private JPanel createPanel(Component comp) {
    JPanel topPanel = new JPanel(new GridBagLayout());

    topPanel.add(comp, new GridBagConstraints(
        0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
    topPanel.add(new JLabel("2"), new GridBagConstraints(
        1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.BOTH, new Insets(0,0,0,0), 0, 0));
    topPanel.add(new JLabel("3"), new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));

    return topPanel;
}

private JPanel getPanelWithLabel() {
    return createPanel(new JLabel("1"));
}

private JPanel getPanelWithPanel() {
    JPanel myPanel = new JPanel(new GridBagLayout());
    myPanel.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
    myPanel.add(new JTextArea(5,25), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
            GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0, 0));
    return createPanel(myPanel);
}

private void init() {
    setTitle("Simple example");
    setSize(800, 200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    JPanel panel = new JPanel(new BorderLayout());
    panel.add(getPanelWithLabel(), BorderLayout.CENTER);
//panel.add(getPanelWithPanel(), BorderLayout.CENTER);

    add(panel);
    setVisible(true);
}

public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            Example ex = new Example();
        }
    });

}
}

我认为您应该将文本区域添加到滚动窗格中,例如 - new JScrollPane(new JTextArea(5,25)) 而不是 new JTextArea(5,25)... 如果您要添加没有滚动窗格的文本区域,网格包布局将尝试将单元格拉伸到由给定到文本区域构造函数的行设置的宽度,无论为给定单元格设置的权重是什么进入网格包结构。

问题出在您 JTextArea 的行上。

由于 25 行比 45% 宽,它会自行扩展。

我不使用 25,而是使用容器 (myPanel)

WIDTH

解决方案

myPanel.add(new JTextArea(5,myPanel.WIDTH), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));

输出


编辑

因为用这种方法尺寸还是有区别的。我尝试先创建一个 JPanel 并向其添加 JLabel


解决方案

JPanel threeCont = new JPanel(new GridBagLayout());
threeCont.add(new JLabel("3"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
// We add myPanel and two(JLabel) to topPanel first and than the below.
topPanel.add(threeCont, new GridBagConstraints(
    2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
    GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));

输出

System.out.println("First Panel's Size : " + myPanel.getSize());
System.out.println("Second Panel's Size : " +two.getSize());
System.out.println("Third Panel's Size : " +threeCont.getSize());

控制台

First Panel's Size : java.awt.Dimension[width=441,height=96]
Second Panel's Size : java.awt.Dimension[width=98,height=96]
Third Panel's Size : java.awt.Dimension[width=441,height=16]

完整代码

public static void main(String[]a) {
    JFrame fr = new JFrame();
    fr.setSize(new Dimension(1000,1000));
    fr.setLocationRelativeTo(null);
    JPanel topPanel = new JPanel(new GridBagLayout());
    Insets INSETS_0PX = new Insets(0,0,0,0);
    JLabel one = new JLabel("1");
    JLabel two = new JLabel("2");
    one.setBackground(Color.yellow);
    two.setBackground(Color.blue);

    JPanel myPanel = new JPanel(new GridBagLayout());
    myPanel.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));
    myPanel.add(new JTextArea(5,myPanel.WIDTH), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
            GridBagConstraints.WEST, GridBagConstraints.BOTH, INSETS_0PX, 0, 0));

    JPanel threeCont = new JPanel(new GridBagLayout());
    threeCont.add(new JLabel("TITLE"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, INSETS_0PX, 0, 0));

    topPanel.add(myPanel, new GridBagConstraints(
        0, 0, 1, 1, 0.45, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));

    topPanel.add(two, new GridBagConstraints(
        1, 0, 1, 1, 0.1, 0.0, GridBagConstraints.WEST,
        GridBagConstraints.BOTH, INSETS_0PX, 0, 0));

    topPanel.add(threeCont, new GridBagConstraints(
        2, 0, 1, 1, 0.45, 0.0, GridBagConstraints.EAST,
        GridBagConstraints.HORIZONTAL, INSETS_0PX, 0, 0));


    fr.add(topPanel);

    fr.setVisible(true);

    System.out.println("First Panel's Size : " + myPanel.getSize());
    System.out.println("Second Panel's Size : " +two.getSize());
    System.out.println("Third Panel's Size : " +threeCont.getSize());
}

weightX 约束适用于额外 space 可用。

因此每个组件都分配有其首选大小。然后,如果在 window 中有额外的 space,则 space 将按指定的百分比分配。

因此,如果您的组件的首选尺寸为:

45、10、45

将面板的宽度增加 100,您将得到:

90, 20, 90.

但如果您从首选尺码开始:

150、20、100

并将面板的宽度增加 100,您将得到:

195、30、145

因此,如果您始终希望应用该比例,则每个组件的首选尺寸也必须在您想要的比例内。

一个选项可能是使用 Relative Layout。它将忽略首选大小,仅根据每个组件的相对约束分配大小。