LayoutManagerCeption - Centering Elements

LayoutManagerCeption - Centering Elements

Java, GUI, Swing

·

2 min read

I have a vision for a project - a multiplayer, web based browser game where users can create rooms and invite their friends. However, I am currently lacking some severe knowledge to build this. Thus, I have decided to build a series of smaller projects to build gain knowledge in one area at a time.

To familiarize myself with networking and sockets, I am building a Java based chat app, using Swing for the GUI. I wanted to keep my design minimal, with two panels. Panel 1 will have 3 components: a label for a prompt, a text field to enter a nickname, and a button to connect, like so: image.png

Right away, I ran into a problem: I could not for the life of me get all three of my components to be both stacked and centered (along both the x and y axis). Messing around with different layout managers resulted in my components being stacked vertically but residing in the top left corner, or cenetered but all 3 components stacked horizontally.

Two trivial solutions came to me:

  1. Manually manipulate each component by adjusting its pixels so they go in the positions I wanted. This code will totally be maintainable.
  2. Move on with the project and focus on the functionality. This is actually the option I chose at first, but after many iterations of starting up the GUI over and over for testing, the uncentered elements turned into an itch that I needed to scratch.

After much experimentation, I was able to find two Layout Managers that each did one part of what I wanted:

Using a BoxLayout layout manager, I was able to stack components together vertically:

JPanel panel = new JPanel(); 
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS); 
JLabel label1 = new JLabel("label1");
JLabel label2 = new JLabel("label2");
panel.add(label1);
panel.add(label2);

Using a GridBagLayout layout manager with default GradBagConstraints, I was able to center my components:

JPanel outerPanel = new JPanel();
outerPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
panel.add(label1, gbc);
panel.add(label2, gbc);

To my surprise, I was able to nest layout managers within layout managers. By nesting my BoxLayout within my GridBagLayout, I was able to achieve my intended result:

public class TestVerticalAlignement {

    protected void initUI() {
        final JFrame frame = new JFrame();
        frame.setTitle("Test vertical alignement");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        JPanel outerPanel = new JPanel();
        outerPanel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        JLabel label = new JLabel("Enter a nickname: ");
        JTextField textField = new JTextField();
        JButton button = new JButton("Connect");
        panel.add(label);
        panel.add(textField);
        panel.add(button);

        outerPanel.add(panel, gbc);
        frame.add(outerPanel);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TestVerticalAlignement().initUI());
    }

}