Question

What is the easiest way to build a form in Java using GroupLayout? With form, I mean something that has text fields with a label in front. Something like this:

Form screenshot

Was it helpful?

Solution

Using Group Layout, you can do the following:

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 );
}
}

OTHER TIPS

Or you ditch the GroupLayout and use the FormLayout, which was primarily designed as a layout for ... forms :-)

Just use the GUI Editor shipped within NetBeans, called Matisse. That is the most amazing GUI editor I've ever seen. It works very very good, and all your windows you design can be made resizable.

This editor produces code using the GroupLayout.

A clone of Matisse is also available as Eclipse plugin, but I don't think it is free. Take a look at it here (Disclaimer: I never used this plugin before, so I can't tell if it is the same quality as the original Matisse)
http://marketplace.eclipse.org/content/swing-gui-designer

Here is a nice screenshot:

enter image description here

An example of how you could achieve the demonstrated layout with 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());
    }
}

The main disadvantage would be that if you wanted to say, add a right-aligned row of buttons (e.g.: "OK" and "Cancel") at the bottom, where the buttons don't align with anything else, you'd have to use a nested JPanel. (Or do something like have the form have a separate column for every button; then have the textfields span over all these columns and an additional spacer column. This is fairly counterintuitive and would negate the readability advantage. I believe MiGLayout, which is a third-party grid-based layout manager can handle this situation neatly though since it allows for merging / spanning grid cells, and splitting the merged cell.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top