Java: GridBagLayout 混淆

4
这是我在这里的第一个问题,请谅解我是否违反了任何规则或没有使用正确的格式。
我正在使用Java Swing创建一个简单的表单,包括1个JLabel标签、1个JTextField文本框和1个Button按钮。
|---------------------------|
|                           |
|           JLabel          |
|                           |
|---------------------------|
|    JTextField    | Button |
|---------------------------|

按钮应该在右下角,JTextField在其左侧,JLabel在顶部,跨越两列。
我希望按钮是固定大小的,JTextField是固定高度的,但使用全部宽度(除了按钮使用的部分),JLabel使用所有其他空间(包括宽度和高度)。
我甚至不确定是否应该使用GridBagLayout或其他布局?
这可能是一个非常简单的问题,但让我困惑了相当长的时间(我猜是因为GridBarLayout有太多选项)。
4个回答

2

边框布局(BorderLayout)类易于使用,但比网格袋布局(GridBagLayout)功能弱。

但当事物简单时,解决方案也必须简单。

panel.add( label, BorderLayout.CENTER );
JPanel south = new JPanel();
south.add( textfield );
south.add( button );
button.setPreferredSize( x, y );
panel.add( south, BorderLayout.SOUTH );

调用setPreferredSize总是在问题的中心运行。 - Guillaume Polet
OP说:“我希望按钮是固定大小的”。 - Aubin
不设置首选大小并不意味着大小会随时间改变(这主要取决于所选择的LayoutManager及其约束条件)。只需不设置首选大小即可。 - Guillaume Polet
@Guillaume Polet:确实,JTextField只是自己的小尺寸,左侧有很多空间,而Button的尺寸是正确的,但不在行的最右侧位置(它后面还有一些空间)。 - Hrqls
@Hrqls Dan建议的解决方案应该可行。你尝试过吗? - Guillaume Polet
显示剩余3条评论

2
首先,将您的面板布局设置为GridBagLayout
然后,创建一个GridBagConstraints对象,并将填充设置为GridBagConstraints.BOTH
对于JLabel,在约束对象上设置以下属性:gridx=0,gridy=0,gridwidth=2,gridheight=2,weightx=1,weighty=1
对于JTextField,在约束对象上设置以下属性:gridx = 0, gridy = 1, gridwidth = 1, gridheight = 1, weightx = 1, weighty = 0
对于JButton,在约束对象上设置以下属性:gridx = 1, gridy = 1, gridwidth = 1, gridheight = 1, weightx = 0, weighty = 0

谢谢你的回答!使用GridBagConstraints,所有组件都显示在同一行(屏幕中央)[空格][JTextField][JLabel][空格][按钮] - Hrqls
我猜我应该使用gridwidth.REMAINDER和gridwidth.RELATIVE....但是我尝试了很多组合,总是搞砸 :)...似乎BorderLayout与2个面板可能是正确的选择..或者是一个BorderLayout与2个面板,并在底部(南)面板内部使用GridBagLayout..虽然这似乎相当复杂,过度处理本应该很简单的事情? - Hrqls
@Hrqls 我添加了一个使用 GBL 和 RELATIVE/REMAINDER 的示例。 - Guillaume Polet

1

好的,这里有一个演示代码,应该可以帮助你开始:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TestGridBagLayout {

    protected void initUI() {
        JFrame frame = new JFrame(TestGridBagLayout.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("A button");
        JTextField textField = new JTextField();
        JLabel label = new JLabel("A cool long nice label that will stretch.");
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setBorder(BorderFactory.createLineBorder(Color.GREEN));
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;// Fill the "cell" in both direction
        gbc.weightx = 1.0;// Allocate extra-width to the label
        gbc.weighty = 1.0;// Allocate extra-height to the label
        gbc.gridwidth = GridBagConstraints.REMAINDER;// The label takes all the available width of the "row"
        panel.add(label, gbc);

        gbc.weighty = 0; // Don't stretch TF vertically
        gbc.fill = GridBagConstraints.HORIZONTAL; // Fill horizontally
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        panel.add(textField, gbc);
        gbc.weightx = 0; // No extra horizontal space is given to the button
        gbc.fill = GridBagConstraints.NONE; // No fill for the button
        panel.add(button, gbc);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestGridBagLayout().initUI();
            }
        });
    }

}

谢谢!这个完美地解决了问题!(它只是在文本字段上下方显示了一些空白,但将其填充更改为“both”就解决了这个问题。谢谢!) - Hrqls

1

我不知道这是否是一种常见的做法,但以下是可行的代码(主要来自Dan和Guillaume的代码)

    //show stuff
    setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    //show label
    c.fill = GridBagConstraints.BOTH;           // Fill the "cell" in both direction
    c.weightx = 1.0;                            // Allocate extra-width to the label
    c.weighty = 1.0;                            // Allocate extra-height to the label
    c.gridwidth = GridBagConstraints.REMAINDER; // The label takes all the available width of the "row"
    add(mlblShow,c);
    //show cmd txt
    c.weighty = 0;                              // Don't stretch TF vertically
c.fill = GridBagConstraints.BOTH;           // Fill horizontally and vertically
c.gridwidth = GridBagConstraints.RELATIVE;
    add(mtxtCmd,c);
    //show send button
     c.weightx = 0;                             // No extra horizontal space is given to the button
 c.fill = GridBagConstraints.NONE;          // No fill for the button
    add(cmdSend,c);

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