Search code examples
javaswingjlabeljtextfieldlayout-manager

Swing getHeight() value changing from 0 to 16


I am trying to make a box in Swing that has a label of "user", a text field for the username, and a button "sign in". This is my code

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

public class Engine
{
    JFrame frame;
    public void go()
    {
        setUpGui();
        userNameScreen();
    }
    public void setUpGui()
    {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    public void userNameScreen()
    {
        JPanel background = new JPanel();
            frame.getContentPane().add(background);
        JLabel labelUserName = new JLabel("User:");
            background.add(labelUserName);
            System.out.println(labelUserName.getHeight()); // 0
        JTextField textFieldUserName = new JTextField();
            System.out.println(labelUserName.getHeight()); // 16
            textFieldUserName.setPreferredSize(new Dimension(110,labelUserName.getHeight()));
            background.add(textFieldUserName);
        JButton buttonSignIn = new JButton("Sign In");
            background.add(buttonSignIn);
        /*
        background.add(labelUserName);
        background.add(textFieldUserName);
        background.add(buttonSignIn);
        frame.getContentPane().add(background);
        */
        frame.pack();
    }
}

My driver class just creates an instance of engine, then runs the method go().
I read that Swing components do not have attributes of height/width until they are added (because that is for the layout manager to decide how much room they have), so it makes sense that in the method userNameScreen(), adding in all components at the end* (commented out here) makes the textFieldUserName variable have no height.
However, you can see in that same method userNameScreen(), I have it do

System.out.println(labelUserName.getHeight());

twice. The first time, it is 0. The second, it is 16. I don't understand why the first time, it would register it as 0. It has already been added to the panel (in the line before), and there doesn't seem to be anything that would change its height between that first println() and the next. So why is the value 0 in the first one, and why does it change to 16 almost immediately after?

*I should note, when I say adding in all the stuff commented out at the end, it also includes removing/commenting out all the same commands done elsewhere in the code.


Solution

  • It is a side effect from not creating/modifying your Swing components on the EDT. Now the EDT is busy doing the layout while you are adding components in another thread.

    Your main method should look like:

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Engine().go();
            }
        });
    }