Search code examples
javaswinglayoutlayout-managergrid-layout

Layout problems with Java Swing Tools


I am trying to make a simple GUI registration code window, that has a text to enter the code, and a button to verify if the code entered is right or wrong. Exactly like this image :

enter image description here

So I tried to do this GUI with java using Java Swing library, and that is my code:

import java.awt.*;
import javax.swing.*;

public class MainClass {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        final JFrame appFrame = new JFrame();
        final JPanel gridPanel = new JPanel(new GridLayout(2,1));
        
        
        Font f = new Font(Font.SERIF, Font.PLAIN, 20);
        JButton registerButton = new JButton("Register!");
        registerButton.setFont(f);
        JTextField verificationCodeText = new JTextField("--Enter your registration key here--");
        
        registerButton.setSize(30,20);
        verificationCodeText.setSize(50,20);
        verificationCodeText.setHorizontalAlignment(SwingConstants.CENTER);
        Border border = BorderFactory.createLineBorder(Color.BLACK, 5);
        verificationCodeText.setFont(f);
        verificationCodeText.setBorder(border);
        
        gridPanel.add(verificationCodeText);
        gridPanel.add(registerButton);
    
        appFrame.add(gridPanel);
        appFrame.setSize(400,400);
        appFrame.setVisible(true);
        
        System.out.println("End");
    }
}

But that what I had obtained :

enter image description here

What can I do with layouts to correct that?

(Note: Ignore the outer black frame in the first image, it is only for clarification purposes)


Solution

  • Best to nest JPanels, mix layouts as needed, and use padding such as via empty borders, which is better than setting size absolutely. Play with code similar to this for instance, the example below uses a BorderLayout as the overall layout, and then adds a FlowLayout using JPanel (default JPanel layout) to the top and a GridBagLayout-using JPanel to the center of the main JPanel. GridBag will center a single component if added in a default (no constraints) fashion:

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.GridBagLayout;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class RegistrationGUI extends JPanel {
        private JButton registerButton = new JButton("Register!");
        private JTextField verificationCodeText = new JTextField("--Enter your registration key here--", 20);
        
        public RegistrationGUI() {
            JPanel topPanel = new JPanel();
            int gap = 35;
            topPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
            verificationCodeText.setHorizontalAlignment(SwingConstants.CENTER);
            topPanel.add(verificationCodeText);
            
            JPanel bottomPanel = new JPanel(new GridBagLayout());
            gap = 60;
            bottomPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
            bottomPanel.add(registerButton);
    
            
            setLayout(new BorderLayout());
            add(topPanel, BorderLayout.PAGE_START);
            add(bottomPanel, BorderLayout.CENTER);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
        private static void createAndShowGui() {
            RegistrationGUI mainPanel = new RegistrationGUI();
            JFrame frame = new JFrame("Registration");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    }