'How can I arrange elements in a javax.swing.* GUI?
I'm trying to create a GUI with 3 components arranged vertically centered in the middle. Now I've created the components but I cannot find a way to add them vertically on top of each other vertically. I've tried making different panels and different layouts and I get something different every time. Any help would greatly be appreciated.
Here's my code:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.GridLayout;
public class EquationSolverGUI extends JFrame {
public static final int WIDTH = 500;
public static final int HEIGHT = 300;;
public EquationSolverGUI() {
super("Equation Solver");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(3, 0));
JPanel panel = new JPanel();
JPanel inputPanel = new JPanel();
JPanel outputPanel = new JPanel();
JPanel buttonPanel = new JPanel();
JTextField input = new JTextField(20);
inputPanel.add(input);
JTextField output = new JTextField(20);
outputPanel.add(output);
JButton solve = new JButton("Solve");
buttonPanel.add(solve);
add(input);
add(output);
add(solve);
panel.add(inputPanel);
panel.add(outputPanel);
panel.add(buttonPanel);
add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
EquationSolverGUI equationSolver = new EquationSolverGUI();
equationSolver.setVisible(true);
}
}
Solution 1:[1]
Take a look at Laying Out Components Within a Container, in particular How to Use GridBagLayout
. GridBagLayout is the most flexible and most complicated in built layout manager, so I'll forgive you if it wasn't immediately obvious.
Based on your needs, I don't think you need individual panels for the components and they could easily be laid out on the same container. If you wanted to have more then one button, grouped together, then I would consider using another panel for those, but the basic concept would otherwise remains the same.
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
JTextField input = new JTextField(20);
JTextField output = new JTextField(20);
JButton solve = new JButton("Solve");
add(input, gbc);
add(output, gbc);
add(solve, gbc);
}
}
}
Solution 2:[2]
You almost had it.
Change this line...
setLayout(new GridLayout(3, 0));
...to be this instead...
setLayout(new GridLayout(0, 1));
...and that will fix everything.
The reason why this fixes everything is because the constructor accepts 2 parameters -- rows and columns. If you set rows to 10, you will get 10 rows. If you set columns to 20, you will get 20, and so on.
However, if you set either rows or columns (NOT BOTH) to equal 0, then you will be permitted to add an infinite number of elements without any unexpected formatting errors.
For example, if I want 20 (or so) elements stacked on top of each other, I would do new GridLayout(0, 1), which is another of saying I want some number of rows, but only 1 column, which is another way of saying, just make one column of an indefinite amount of elements. It works vice versa for horizontal, just make it new GridLayout(1, 0).
This is important because if you try to plug in more elements than expected, and you don't use the 0-style format, you will get unexpected and likely unwanted results. Here is an example.
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.GridLayout;
public class LayoutTrouble
{
public static void main(String[] args)
{
gridLayoutWithMoreElementsThanPlanned(3, 1, 300, 400);
gridLayoutWithMoreElementsThanPlanned(0, 1, 600, 400);
}
private static void gridLayoutWithMoreElementsThanPlanned(final int rows, final int columns, final int x, final int y)
{
final JFrame frame = new JFrame();
final JPanel panel = new JPanel();
panel.setLayout(new GridLayout(rows, columns));
panel.add(new JButton("1"));
panel.add(new JButton("2"));
panel.add(new JButton("3"));
panel.add(new JButton("4"));
frame.add(panel);
frame.setTitle("4 buttons in a " + rows + " by " + columns);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocation(x, y);
frame.setVisible(true);
}
}
As you can see in this image, using the 0-style protects you from accidentally miscounting the number of elements. Now, the result remains as expected without any surprises.
As you can see though, you can still add an infinite number of elements without using 0-style, but I strongly recommend that you do not do this. The behaviour is difficult to follow, and unnecessarily complicates your domain. Instead, it's much easier to either use 0-style, or find some way to assert the number of elements being added.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MadProgrammer |
| Solution 2 |


