【问题标题】:How can I use GroupLayout to build a form?如何使用 GroupLayout 构建表单?
【发布时间】:2012-07-11 04:06:18
【问题描述】:

使用 GroupLayout 在 Java 中构建表单的最简单方法是什么?对于表单,我的意思是前面带有标签的文本字段。像这样的:

【问题讨论】:

  • 我不会真的推荐 GroupLayout 进行手动编码。这是可能的,但难度曲线很陡,您需要事先绘制设计草图才能正确设置对齐约束。它实际上主要用于 Netbeans 设计器,主要优点是它可以让您避免嵌套面板,而不是清除代码。
  • 我以前从未使用过 GroupLayout,并且在 1 小时左右后能够想出这个。布局和调整大小的行为比使用 GridLayout 好得多,大多数 Swing 编程新手可能会使用它。
  • 我没有说用GroupLayout 手工编码是不可能的,我只是不认为这是一个很好的选择。每个组件都必须分成两组,可能有很多行代码分开。这使得生成的代码本质上是只写的,因为您必须在脑海中保留多少约束才能弄清楚什么渲染在哪里以及为什么渲染。即使对于您几乎微不足道的示例,与使用GridBagLayout 相比,查看代码并弄清楚其意图可能要困难得多。 (这应该可以让您在不到一小时的时间内获得正确的调整大小行为。)

标签: java swing grouplayout


【解决方案1】:

使用Group Layout,您可以执行以下操作:

package foo;

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

public class ChangeIpSettingsDialog extends JDialog
{
public ChangeIpSettingsDialog( Frame owner )
{
    super( owner, true );
    setContentPane( createContent() );
}

private Container createContent()
{
    JPanel result = new JPanel();
    result.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10 ) );

    // Create the layout
    GroupLayout layout = new GroupLayout( result );
    result.setLayout( layout );
    layout.setAutoCreateGaps( true );

    // Create the components we will put in the form
    JLabel ipAddressLabel = new JLabel( "IP Address:" );
    JTextField ipAddressTextField = new JTextField( 20 );
    JLabel subnetLabel = new JLabel( "Subnet:" );
    JTextField subnetTextField = new JTextField( 20 );
    JLabel gatewayLabel = new JLabel( "Gateway:" );
    JTextField gatewayTextField = new JTextField( 20 );

    // Horizontally, we want to align the labels and the text fields
    // along the left (LEADING) edge
    layout.setHorizontalGroup( layout.createSequentialGroup()
                                       .addGroup( layout.createParallelGroup( GroupLayout.Alignment.LEADING )
                                                          .addComponent( ipAddressLabel )
                                                          .addComponent( subnetLabel )
                                                          .addComponent( gatewayLabel ) )
                                       .addGroup( layout.createParallelGroup( GroupLayout.Alignment.LEADING )
                                                          .addComponent( ipAddressTextField )
                                                          .addComponent( subnetTextField )
                                                          .addComponent( gatewayTextField ) )
    );

    // Vertically, we want to align each label with his textfield
    // on the baseline of the components
    layout.setVerticalGroup( layout.createSequentialGroup()
                                     .addGroup( layout.createParallelGroup( GroupLayout.Alignment.BASELINE )
                                                        .addComponent( ipAddressLabel )
                                                        .addComponent( ipAddressTextField ) )
                                     .addGroup( layout.createParallelGroup( GroupLayout.Alignment.BASELINE )
                                                        .addComponent( subnetLabel )
                                                        .addComponent( subnetTextField ) )
                                     .addGroup( layout.createParallelGroup( GroupLayout.Alignment.BASELINE )
                                                        .addComponent( gatewayLabel )
                                                        .addComponent( gatewayTextField ) )
    );

    return result;
}

public static void main( String[] args )
{
    ChangeIpSettingsDialog dialog = new ChangeIpSettingsDialog( null );
    dialog.pack();
    dialog.setVisible( true );
}
}

【讨论】:

    【解决方案2】:

    或者您放弃 GroupLayout 并使用 FormLayout,它主要设计为...表单的布局:-)

    【讨论】:

    • 对于截图中的例子,即使是GridBagLayout也应该足够了。
    • @Robin 我通常总是为此使用 FormLayout,但我的要求是不要使用外部库,而只能使用 Java 中的 layoutmanagers。
    • @WimDeblauwe 可能值得在您的问题中明确提及这一点
    • 请注意,同时最新版本 (1.13) 仅在商业版本中可用。开源版本 (1.9) 可以从下载档案中下载。网站上未提供文档。
    【解决方案3】:

    只需使用 NetBeans 附带的 GUI 编辑器,称为 Matisse。这是我见过的最神奇的 GUI 编辑器。它工作得非常好,你设计的所有窗口都可以调整大小。

    此编辑器使用 GroupLayout 生成代码。

    Matisse 的克隆也可用作 Eclipse 插件,但我不认为它是免费的。看看这里(免责声明:我以前从未使用过这个插件,所以我无法判断它是否与原始 Matisse 质量相同)
    http://marketplace.eclipse.org/content/swing-gui-designer

    这是一个不错的截图:

    【讨论】:

    • +1:Matisse 非常好用,可惜 NetBeans 的其余部分没有达到同样的水平(不得不承认,我用了 Eclipse 多年可能有点偏见) .
    【解决方案4】:

    如何使用GridBagLayout 实现演示布局的示例:

    class Main extends JFrame implements Runnable {
    
        JLabel lblIpAddress = new JLabel();
        JLabel lblSubnet = new JLabel();
        JLabel lblGateway = new JLabel();
    
        JTextField txtIpAddress = new JTextField();
        JTextField txtSubnet = new JTextField();
        JTextField txtGateway = new JTextField();
    
        public void run() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Container content = this.getContentPane();
    
            lblIpAddress.setText("IP Address");
            lblIpAddress.setLabelFor(txtIpAddress);
            lblSubnet.setText("Subnet");
            lblSubnet.setLabelFor(txtSubnet);
            lblGateway.setText("Gateway");
            lblGateway.setLabelFor(txtGateway);
    
            GridBagLayout layout = new GridBagLayout();
            content.setLayout(layout);
    
            content.add(lblIpAddress, newLabelConstraints());
            content.add(txtIpAddress, newTextFieldConstraints());
            content.add(lblSubnet, newLabelConstraints());
            content.add(txtSubnet, newTextFieldConstraints());
            content.add(lblGateway, newLabelConstraints());
            content.add(txtGateway, newTextFieldConstraints());
    
            // Add a spacer to push all the form rows to the top of the window.
            GridBagConstraints spacer = new GridBagConstraints();
            spacer.fill=BOTH;
            spacer.gridwidth=REMAINDER;
            content.add(new JPanel(), spacer);
    
            // make sure you can't "cut off" the controls when making the window smaller
            this.pack();
            this.setMinimumSize(this.getSize());
    
            this.setVisible(true);
        }
    
        private GridBagConstraints newConstraints() {
            GridBagConstraints c = new GridBagConstraints();
            // a little breathing room
            c.insets = new Insets(2, 2, 2, 2);
            return c;
        }
    
        private GridBagConstraints newLabelConstraints() {
            GridBagConstraints c = newConstraints();
            // right-align labels
            c.anchor = BASELINE_TRAILING;
            // do not grow labels
            c.weightx=0.0;
            return c;
        }
    
        private GridBagConstraints newTextFieldConstraints() {
            GridBagConstraints c = newConstraints();
            c.anchor = BASELINE;
            // grow text fields horizontally
            c.weightx=1.0;
            c.fill=HORIZONTAL;
            // text fields end a row
            c.gridwidth=REMAINDER;
            return c;
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Main());
        }
    }
    

    主要的缺点是,如果你想说,在底部添加一排右对齐的按钮(例如:“确定”和“取消”),这些按钮与其他任何东西都不对齐,你必须使用嵌套的 JPanel。 (或者做一些事情,比如让表单为每个按钮都有一个单独的列;然后让文本字段跨越所有这些列和一个额外的间隔列。这是相当违反直觉的,并且会否定可读性优势。我相信 MiGLayout,这是第三个-party 基于网格的布局管理器可以巧妙地处理这种情况,因为它允许合并/跨越网格单元格,拆分合并的单元格。)

    【讨论】:

    • run 中添加this.setBounds(0,0,300,300) 以显示JFrame(可能是Linux 和/或OpenJDK 的东西,但不会受到伤害)。关于答案:那还不够。如果您可以发布在您的环境中运行的结果图片,那就太好了,以便有更好的基础进行讨论。在我的情况下,文本字段的大小并不合适,即根本没有。
    • @KarlRichter - a) 时间机器可以访问“我的环境”;或者 b)我在很久没有接触 Java 之后又费心重新设置 Java,以改善似乎不是很多人(包括 OP)关心的答案,在一个具有不同接受答案的问题上。我不会发誓三年前它对我来说是正确的,但如果它现在不起作用,我还不如取消我的答案。
    • @KarlRichter 另外,如果您遇到与 OP 类似的问题,并且由于某种原因接受的答案对您没有帮助,我建议您提出一个包含原因的新问题。
    猜你喜欢
    • 2013-04-15
    • 1970-01-01
    • 2017-04-11
    • 2011-05-25
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多