I am trying to create a form in Swing.
The form should look similar to this:
____________________________________
|___________________________________X|
| |
| ________________ |
| label1 [________________] |
| ________________ |
| label2 [________________] |
| |
| |
| [Save] [Close] |
|____________________________________|
But I'm having trouble center aligning the text fields vertically.
Below is the code for opening the frame:
public class Main {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
LayoutTest test = new LayoutTest();
test.setVisible(true);
}
});
}
}
Here is the code for initialing the fields and creating the layout:
public class LayoutTest {
private JFrame testFrame;
JLabel label1;
JTextField field1;
JLabel label2;
JTextField field2;
JButton saveButton;
JButton closeButton;
public LayoutTest() {
testFrame = new JFrame();
initProperties();
initContent();
initLayout();
}
private void initProperties() {
testFrame.setTitle("Test");
testFrame.setSize(1000, 800);
testFrame.setLocationRelativeTo(null);
testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private void initContent() {
label1= new JLabel("Label 1");
field1= new JTextField(25);
label1.setLabelFor(field1);
label2= new JLabel("Label 2");
field2= new JTextField(25);
label2.setLabelFor(field2);
saveButton = new JButton("Save");
closeButton = new JButton("Close");
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
testFrame.add(label1);
testFrame.add(field1);
testFrame.add(label2);
testFrame.add(field2);
testFrame.add(saveButton);
testFrame.add(closeButton);
}
private void initLayout() {
SpringLayout layout = new SpringLayout();
layout.putConstraint(SpringLayout.NORTH, label1, 10, SpringLayout.NORTH, testFrame.getContentPane());
layout.putConstraint(SpringLayout.EAST, label1, -5, SpringLayout.WEST, field1);
layout.putConstraint(SpringLayout.NORTH, field1, 10, SpringLayout.NORTH, testFrame.getContentPane());
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, field1, -10, SpringLayout.HORIZONTAL_CENTER, testFrame.getContentPane());
layout.putConstraint(SpringLayout.NORTH, label2, 10, SpringLayout.SOUTH, label1);
layout.putConstraint(SpringLayout.EAST, label2, -5, SpringLayout.WEST, field2);
layout.putConstraint(SpringLayout.NORTH, field2, 5, SpringLayout.SOUTH, field1);
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, field2, -10, SpringLayout.HORIZONTAL_CENTER, testFrame.getContentPane());
layout.putConstraint(SpringLayout.SOUTH, closeButton, -20, SpringLayout.SOUTH, testFrame.getContentPane());
layout.putConstraint(SpringLayout.EAST, closeButton, -20, SpringLayout.EAST, testFrame.getContentPane());
layout.putConstraint(SpringLayout.SOUTH, saveButton, -20, SpringLayout.SOUTH, testFrame.getContentPane());
layout.putConstraint(SpringLayout.EAST, saveButton, -10, SpringLayout.WEST, closeButton);
testFrame.setLayout(layout);
}
public void setVisible(boolean visible) {
testFrame.setVisible(visible);
}
}
I've tried to add the fields to a panel and then use SpringLayout.VERTICAL_CENTER
on the panel but nothing showed up.
How can I center align the fields as a group?
You have any number of options depending on your needs. I prefer GridBagLayout
, but that's cause I've been using for 15 years.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FormLayout {
public static void main(String[] args) {
new FormLayout();
}
public FormLayout() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(8, 8, 8, 8);
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("Label 1"), gbc);
gbc.gridy++;
add(new JLabel("Label 2"), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridy = 0;
gbc.gridx++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JTextField(20), gbc);
gbc.gridy++;
add(new JTextField(20), gbc);
gbc.gridy++;
gbc.gridx++;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 1;
add(new JButton("Save"), gbc);
gbc.weightx = 0;
gbc.gridx++;
add(new JButton("Close"), gbc);
}
}
}
The problem with this, for me, is the buttons will stay in the middle of form, near the fields, as the window is resized
You might not mind this, but it annoys me. I'd prefer to use a compound layout approaching, placing the content in a separate panel and the buttons in another. It means I get to use the power of three layout managers instead of just one...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FormLayout {
public static void main(String[] args) {
new FormLayout();
}
public FormLayout() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JPanel content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(8, 8, 8, 8);
gbc.anchor = GridBagConstraints.EAST;
content.add(new JLabel("Label 1"), gbc);
gbc.gridy++;
content.add(new JLabel("Label 2"), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridy = 0;
gbc.gridx++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
content.add(new JTextField(20), gbc);
gbc.gridy++;
content.add(new JTextField(20), gbc);
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttons.add(new JButton("Save"));
buttons.add(new JButton("Close"));
add(content);
add(buttons, BorderLayout.SOUTH);
}
}
}
The choice however, is your own...