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:
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 );
}
}
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:
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.)
this.setBounds(0,0,300,300)
in run
to display the JFrame
(might be a Linux and/or OpenJDK thing, but doesn't hurt). Regarding the answer: That doesn't quite do it. It'd be nice if you could post a picture of the result running in your environment so that there's a better base to discuss. In my case the text fields don't size well, i.e. at all. –
Neurotic © 2022 - 2024 — McMap. All rights reserved.
GroupLayout
for hand-coding. It's possible, but the difficulty curve is steep, and you need to have the design sketched up beforehand to get the alignment constraints right. It's really mainly intended to be used with the Netbeans designer, and the primary advantage is that it lets you avoid having to nest panels, not clear code. – ImagismGridLayout
for example, which most newbies to Swing programming would probably use for this. – HegelianismGroupLayout
, I just don't think it's a very good option. Every component has to be placed into two groups, possibly many lines of code apart. This makes the resulting code essentially write-only because of how many constraints you have to keep in your head to figure out what renders where and why. Even for your nearly trivial example it's probably much harder to look at the code and figure out its intent than when usingGridBagLayout
. (Which should let you get the right resize behaviour in much less than one hour.) – Imagism