Search code examples
javaswingjframejpaneljlabel

Java Swing - Center a JLabel using BorderLayout


I have an assignment, and the instructions specify that I need two labels to be centered on the screen (both horizontally and vertically).
I know this question has been asked many times, but whenever I have searched for this question, the solution given is often to use a different layout manager, like BoxLayout. However, the instructions also specify that I must use BorderLayout.
Originally I did not add the labels to a panel and instead added them directly to the frame, but this didn't work, so I was advised to put them both on a JPanel, which hasn't worked either.

My code looks like this currently:

    JButton butSubmit = new JButton("Submit");
    JButton butReset = new JButton("Reset");

    JLabel nameAndReg = new JLabel("My details", SwingConstants.CENTER);
    JLabel errorMsg = new JLabel("The error message", SwingConstants.CENTER);
    nameAndReg.setForeground(Color.blue);

    JTextField redVal = new JTextField(3);
    JTextField greenVal = new JTextField(3);
    JTextField blueVal = new JTextField(3);

    JPanel butPanelSouth = new JPanel();
    JPanel butPanelNorth = new JPanel();
    JPanel labsPanel = new JPanel();

    butPanelSouth.add(redVal);
    butPanelSouth.add(greenVal);
    butPanelSouth.add(blueVal);
    butPanelSouth.add(butSubmit);
    butPanelNorth.add(butReset);
    labsPanel.add(nameAndReg, BorderLayout.CENTER);
    labsPanel.add(errorMsg, BorderLayout.CENTER);

    add(labsPanel, BorderLayout.CENTER);
    add(butPanelNorth, BorderLayout.NORTH);
    add(butPanelSouth, BorderLayout.SOUTH);

And this is what it produces: Current result
How can I get 'My details' and 'The error message' to be vertically and horizontally in the middle of the window, one under the other, and still use BorderLayout?

Edit: Sorry, I realise I wasn't very clear. The advice I was given was 'perhaps nest your layout managers i.e. put a JPanel in the centre of a BorderLayout on a JFrame.'


Solution

  • As i said in the comment above, you should clarify what do you mean when you say "the instructions also specify that I must use BorderLayout".

    If you mean that your content pane must have a BorderLayout, and the other panels can have a different layout (like in your code, since you are using a FlowLayout in your sub panels), it's easy to solve your issue.

    You just need to add your labels in a JPanel which uses a layout that aligns the labels at the center, like GridBagLayout does. Your first label will have gridx = 0 and gridy = 0, the second label will have gridx = 0 and gridy = 1. Your second will be exactly below the first one, you can use insets to create some empty space (in the code below i use 5 pixels for Insets.top).

    Since your labsPanel will be at BorderLayout.CENTER, the panel will take all the empty space in your frame, and GridBagConstrains.anchor default value (GridBagConstrains.CENTER) makes sure your labels are centered inside your labsPanel. As a result, the labels will be vertically and horizontally aligned at the middle of the frame, like in the screeenshot below:

    enter image description here

    Code sample:

    import java.awt.*;
    import javax.swing.*;
    public class Test
    {
        public static void main (String [] a) {
            SwingUtilities.invokeLater (new Runnable () {
                @Override public void run () {
                    createAndShowGUI ();
                }
            });
        }
        private static void createAndShowGUI () {
            JFrame frame = new JFrame ("Test");
            frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
            frame.setContentPane (new MainPanel ());
            frame.pack ();
            frame.setLocationRelativeTo (null);
            frame.setVisible (true);
        }
    }
    class MainPanel extends JPanel
    {
        public MainPanel () {
            super (new BorderLayout ());
    
            JLabel nameAndReg = new JLabel ("My details", SwingConstants.CENTER);
            JLabel errorMsg = new JLabel ("The error message", SwingConstants.CENTER);
            nameAndReg.setForeground(Color.blue);
    
            JPanel labsPanel = new JPanel (new GridBagLayout ());
    
            labsPanel.add (nameAndReg);
    
            GridBagConstraints c = new GridBagConstraints ();
            c.gridy = 1;
            c.insets = new Insets (5, 0, 0, 0);
            labsPanel.add (errorMsg, c);
    
            JButton butSubmit = new JButton("Submit");
            JButton butReset = new JButton("Reset");
    
            JTextField redVal = new JTextField(3);
            JTextField greenVal = new JTextField(3);
            JTextField blueVal = new JTextField(3);
    
            JPanel butPanelSouth = new JPanel ();
            JPanel butPanelNorth = new JPanel ();
    
            butPanelSouth.add (redVal);
            butPanelSouth.add (greenVal);
            butPanelSouth.add (blueVal);
            butPanelSouth.add (butSubmit);
    
            butPanelNorth.add (butReset);
    
            add (labsPanel, BorderLayout.CENTER);
            add (butPanelNorth, BorderLayout.NORTH);
            add (butPanelSouth, BorderLayout.SOUTH);
        }
    }
    

    If all your panels must have a BorderLayout, it's very difficult to achieve what you want, but as i said, it would be a crazy requirement.