如何使组件跨越 GridBagLayout 中的多个单元格

Posted

技术标签:

【中文标题】如何使组件跨越 GridBagLayout 中的多个单元格【英文标题】:How can I make a component span multiple cells in a GridBagLayout 【发布时间】:2013-06-16 18:51:24 【问题描述】:

我必须为学校做这个:

这是我目前的代码:

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

public class AddressBookGui1 extends JFrame 
public AddressBookGui1()

    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    setLayout(gbl);

    JLabel label;
    JButton button;
    JTextField textField;
    JTextArea textArea = new JTextArea(10, 20);

    gbc.weightx = 1;
    label = new JLabel("text");
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 0;
    gbc.gridy = 0;
    add(label ,gbc);

    textField = new JTextField();
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 1;
    gbc.gridy = 0;
    add(textField ,gbc);

    label = new JLabel("text");
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridwidth = 1;
    add(label ,gbc);

    textField = new JTextField();
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.gridwidth = 2;
    add(textField, gbc);

    label = new JLabel("text");
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.gridwidth = 1;
    add(label ,gbc);

    textField = new JTextField();
    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.gridwidth = 2;
    add(textField, gbc);

    label = new JLabel("text");
    gbc.weightx = 1;
    gbc.anchor = GridBagConstraints.FIRST_LINE_START;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 0;
    gbc.gridy = 3;
    gbc.gridwidth = 1;
    add(label ,gbc);



    gbc.weightx = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.gridwidth = 2;
    gbc.gridx = 1;
    gbc.gridy = 3;

    add(textArea, gbc);

    gbc.weightx = 1;
    button = new JButton("text");
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridwidth = 1;
    gbc.gridx = 0;
    gbc.gridy = 4;
    add(button ,gbc);

    gbc.weightx = 1;
    button = new JButton("text");
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 3;
    gbc.gridy = 4;
    add(button ,gbc);




public static void main(String[] args)
  AddressBookGui1 frame = new AddressBookGui1();
  frame.setTitle("Address Book");
  frame.setSize(400, 300);
  frame.setLocationRelativeTo(null);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true); 



(我仍然需要处理填充和插入。我已经让它们在一个更简单的程序中工作,所以我想我已经掌握了这些东西)

我已经尝试了 GridBagLayout Oracle 教程,但我不确定我做错了什么。有人可以帮我让它看起来更像它应该的样子吗?专门使文本字段和文本区域跨越 2 个单元格。

【问题讨论】:

Specifically to make the text fields and text area span over 2 cells - 为什么必须跨越两个单元格?在您的图片中,您有 2 列和 5 行。您唯一需要更改的是使按钮右对齐。为此,我想你需要和锚一起玩。再次查看教程。 我有 3 列。最后一个按钮在第 3 列中。 This is the grid I'm looking to make 这可能是您对作业的解释,但不需要我已经说过的 3 列。您只需要在第二列中右对齐按钮即可。如果分配的目标是创建 3 列并使用 gridwidth 约束,那很好,但这不是必需的。我猜你的问题是“文本”按钮的gridx=3。请记住,行/列的偏移量为 0,因此您尝试将按钮定位在第 4 列,而不是第 3 列。 【参考方案1】:

gbc.gridwidth 是允许组件跨越多列的参数。例如,如果您有 3 列和 4 行并且您希望标签占据完整的顶行,那么您需要为标签分配第一个单元格。并设置 gbc.gridwidth = 3;

【讨论】:

【参考方案2】:

我注意到你的代码的几件事。

不要使用 JFrame 的setSize()。这将导致异常行为。 取而代之的是,让框架根据其大小自行调整大小 成分。如果您希望框架更大,请不要调整大小 框架,但其中的组件。你可以 setpreferredSize 或覆盖组件的 getpreferredsize 如果 您真正想要调整的是大小,因为 GridBagLayout 是那些尊重 组件的首选大小。使用pack() 删除不必要的 空间。

不要扩展 JFrame,让你的 UI 类有一个主面板和 在那里添加所有组件。为该面板提供一个吸气剂(例如 getUI()) 用于提取该类的 UI。

始终重新实例化 GridBagConstraints 对象 将应用于另一个组件。这种方式更 可读。

使用 insets 在组件周围放置填充。

不要重复使用对不同组件的相同引用;

使用Initial Thread

这不是标准的,但我发现它在工作时非常有用 使用GridBagLayout,在设置gbc的约束时,使其进入 按字母顺序。

为了解决您的问题,这里是修改后的代码,其中包含我指出的内容。

public class AddressBook 

    private JPanel pnlMain;

    public AddressBook() 
        pnlMain = new JPanel();
        pnlMain.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        JLabel lblName = new JLabel("Name");
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(0, 10, 0, 0);
        gbc.weightx = 1;
        pnlMain.add(lblName, gbc);

        JTextField txtName = new JTextField();
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 3;
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.insets = new Insets(5, 0, 0, 10);
        gbc.weightx = 1;
        pnlMain.add(txtName, gbc);

        JLabel lblPhone = new JLabel("Phone");
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 1;
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.insets = new Insets(0, 10, 0, 0);
        gbc.weightx = 1;
        pnlMain.add(lblPhone, gbc);

        JTextField txtPhone = new JTextField();
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 3;
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.insets = new Insets(5, 0, 0, 10);
        gbc.weightx = 1;
        pnlMain.add(txtPhone, gbc);

        JLabel lblEmail = new JLabel("Email");
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 1;
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.insets = new Insets(0, 10, 0, 0);
        gbc.weightx = 1;
        pnlMain.add(lblEmail, gbc);

        JTextField txtEmail = new JTextField();
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 3;
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.weightx = 1;
        gbc.insets = new Insets(5, 0, 0, 10);
        pnlMain.add(txtEmail, gbc);

        JLabel lblAddress = new JLabel("Address");
        gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = 1;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.insets = new Insets(0, 10, 0, 0);
        gbc.weightx = 1;
        pnlMain.add(lblAddress, gbc);

        JTextArea txtAreaAddress = new JTextArea(10, 20);
        JScrollPane pane = new JScrollPane(txtAreaAddress);
        gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.NORTH;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridwidth = 3;
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.insets = new Insets(5, 0, 0, 10);
        gbc.weightx = 1;
        pnlMain.add(pane, gbc);

        JButton btnSave = new JButton("Save");
        gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridwidth = 1;
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.insets = new Insets(10, 10, 10, 0);
        gbc.weightx = 1;
        pnlMain.add(btnSave, gbc);

        JButton btnCancel = new JButton("Cancel");
        gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.EAST;
        gbc.gridwidth = 1;
        gbc.gridx = 3;
        gbc.gridy = 4;
        gbc.insets = new Insets(10, 0, 10, 10);
        gbc.weightx = 1;
        pnlMain.add(btnCancel, gbc);

    

    public JPanel getUI()
        return pnlMain;
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 
                JFrame frame = new JFrame("Address Book");
                frame.getContentPane().add(new AddressBook().getUI());
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            
        );
    


【讨论】:

以上是关于如何使组件跨越 GridBagLayout 中的多个单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 GridBagLayout 防止组件抖动?

如何使用 GridBagLayout 定位组件?

使用GridBagLayout控制行列的高度和宽度

如何使用 GridBagLayout 在 JPanel 中对齐组件中心?

GridBagLayout中的Make Component占用相同的宽度

如何在 GridBagLayout 中调整 JPanel 的大小?