尝试添加另一个具有自己的布局和标签作为其一部分的 JPanel 时,Java Swing GridBagLayout 无法按预期工作

问题描述 投票:0回答:1

我有一个任务,需要使用 JavaSwing 复制特定布局。我决定使用 GridBagLayout,因为它看起来非常灵活,但当我尝试添加另一个具有自己的布局的 JPanel 作为网格的一部分时,它没有按预期响应。

代码如下:

/*
 * GridBagLayoutDemo.java requires no other files.
 */

import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class JavaSwingLayout {
    final static boolean shouldFill = true;
    final static boolean shouldWeightX = true;
    final static boolean RIGHT_TO_LEFT = false;

    public static void addComponentsToPane(Container pane) {
        if (RIGHT_TO_LEFT) {
            pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        }

        JLabel label;
        JPanel section;
        Color color;
        pane.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();

        if (shouldFill) {
            // natural height, maximum width
            c.fill = GridBagConstraints.VERTICAL;
        }

        // Turquoise
        label = new JLabel();
        label.setOpaque(true);
        color = new Color(76, 235, 169);
        label.setBackground(color);

        c.fill = GridBagConstraints.VERTICAL;
        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 4;
        c.ipadx = 150;
        c.ipady = 100;
        c.insets = new Insets(5, 5, 5, 5);
        pane.add(label, c);

        // Section
        section = new JPanel();
        section.setLayout(new GridBagLayout());  

        c.fill = GridBagConstraints.NONE;
        c.gridx = 0;
        c.gridy = 4;
        c.gridheight = 4;
        c.ipadx = 0;
        c.ipady = 0;
        c.weighty = 0;
        c.weightx = 0;
        c.insets = new Insets(0, 0, 0, 0);
        pane.add(section, c);

        // red
        label = new JLabel();
        label.setOpaque(true);
        color = new Color(254, 0, 0);
        label.setBackground(color);

        c.fill = GridBagConstraints.VERTICAL;
        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 1;
        c.ipadx = 50;
        c.ipady = 33;
        c.insets = new Insets(0, 0, 0, 0);
        section.add(label, c);
        
        // orange
        label = new JLabel();
        label.setOpaque(true);
        label.setOpaque(true);
        color = new Color(255, 109, 0);
        label.setBackground(color);

        c.fill = GridBagConstraints.BOTH;
        c.gridx = 0;
        c.gridy = 1;
        c.gridheight = 2;
        c.ipadx = 0;
        c.ipady = 0;
        section.add(label, c);


        //magenta
        label = new JLabel();
        label.setOpaque(true);
        label.setOpaque(true);
        color = new Color(240, 0, 255);
        label.setBackground(color);
    
        c.fill = GridBagConstraints.BOTH;
        c.gridx = 1;
        c.gridy = 0;
        c.gridheight = 3;
        c.gridwidth = 2;
        c.ipadx = 100;
        c.ipady = 100;
        section.add(label, c);
    

        // Green
        label = new JLabel();
        label.setOpaque(true);
        color = new Color(56, 120, 0);
        label.setBackground(color);

        c.fill = GridBagConstraints.VERTICAL;
        c.gridx = 1;
        c.gridy = 0;
        c.gridheight = 2;
        c.ipadx = 100;
        c.ipady = 50;
        c.insets = new Insets(5, 5, 5, 5);
        pane.add(label, c);

        // Blue
        label = new JLabel();
        label.setOpaque(true);
        color = new Color(1, 80, 159);
        label.setBackground(color);

        c.fill = GridBagConstraints.VERTICAL;
        c.gridx = 1;
        c.gridy = 2;
        c.gridheight = 5;
        c.ipady = 115;
        pane.add(label, c);
            
        // Tan
        label = new JLabel();
        label.setOpaque(true);
        color = new Color(201, 157, 97);
        label.setBackground(color);

        c.fill = GridBagConstraints.VERTICAL;
        c.gridx = 1;
        c.gridy = 7;
        c.gridheight = 1;
        c.ipady = 25;
        pane.add(label, c);
    }

    /**
     * Create the GUI and show it. For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        // Create and set up the window.
        JFrame frame = new JFrame("GridBagLayoutDemo");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Set up the content pane.
        addComponentsToPane(frame.getContentPane());

        // Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

输出如下图所示:

enter image description here

但是我希望 JPanel 称为具有自己的 GridBagLayout 的部分不要像那样垂直拉伸 JLabel 之间的空间,我希望它占据与上面的绿松石色 JLabel 相同的空间。

在将 JLabels 添加到 JPanel 部分之前,它看起来像这样:

enter image description here

但是添加它们之后,它扭曲了它应该占用的空间,并且尽管我尝试了很多,但似乎无法修复它。

java swing layout
1个回答
0
投票

GridBag布局建议

尝试将其添加到

addComponentsToPane
的底部:

for (int y = 0; y < 8; y++) {
    pane.add(Box.createVerticalStrut(0), new GridBagConstraints(
        2, y, 0, 1, 0, 1,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        new Insets(0, 0, 0, 0), 0, 0));
}

我认为您正在接近布局,就像在方格纸上填充单元格一样。为了让 GridBagLayout 以同样的方式处理它:它有助于在 8 行的每一行上放置一些东西。因此,使用这段代码:我们在每一行添加一个空的 0x0 框。这有助于强制 GridBagLayout 按照您的方式来考虑每一行。

通过此更改:绿松石框和

section
分配 相同的高度。但是
section
还没有填满它的高度。如果(?)您希望它填充该高度,您可以首先添加:

c.fill = GridBagConstraints.VERTICAL;
section.setBorder(new LineBorder(Color.black));
pane.add(section, c);

边框有助于确认

section
已拉伸到适当的高度。然后,您需要进入
section
的布局内部,并为所有这些元素赋予 y 权重并填充,以便它们能够拉伸以填充可用空间。

替代建议

除非您有迫切需要以这种方式处理它:我建议不要使用一个 GridBagLayout 来实现此 UI。 GridBagLayouts 可能很脆弱/棘手;如果修改一个单元格的一项属性,可能会破坏其他单元格。

如果您使用嵌套面板来实现此目的:我认为您可以避免使用 GridBagLayouts 并在 3 个面板中的 2 个中使用其更简单的表兄弟

GridLayout
。我会尝试类似的事情:

  1. 首先实现一个2列面板:
JPanel outermostRow = new JPanel(new GridLayout(1,2));
outermostRow.add(createLeftColumn());
outermostRow.add(createRightColumn());
  1. 左列可以是 2 行面板:
private static JPanel createLeftColumn() {
    JPanel returnValue = new JPanel(new GridLayout(2, 1));
    returnValue.add(turquoiseBox);
    returnValue.add(section);
    return returnValue;
}
  1. 右列可以使用原始代码中的 GridBagLayout。
© www.soinside.com 2019 - 2024. All rights reserved.