6

I have been experimenting with making GUIs in java as opposed to just using "static" all the time and come across the "SwingUtilities.invokeLater()" method. I manage to get everything setup but when it comes to run the application, nothing appears on the JPanel until I resize the window. Is there a fix for this or am I doing it wrong?

Heres my code:

public class main extends JPanel implements ActionListener{ 
public JLabel userLabel;
public JLabel passLabel;
public JTextField userField;
public JTextField passField;
public JButton login;
public JButton closeLogin;
public JButton help;

public main(){
    userLabel = new JLabel("Username: ");
    passLabel = new JLabel("Password: ");
    userField = new JTextField(16);
    passField = new JTextField(16);

    login = new JButton("Login");
    login.setActionCommand("login");
    login.setMnemonic(KeyEvent.VK_L);
    closeLogin = new JButton("Close");
    closeLogin.setActionCommand("closeLogin");
    closeLogin.setMnemonic(KeyEvent.VK_E);
    help = new JButton("Help");
    help.setActionCommand("helpLogin");
    help.setMnemonic(KeyEvent.VK_H);

    login.addActionListener(this);
    closeLogin.addActionListener(this);
    help.addActionListener(this);

    add(userLabel);
    add(userField);
    add(passLabel);
    add(passField);
    add(login);
    add(help);
    add(closeLogin);

}
public void actionPerformed(ActionEvent e){ 
}
public static void initComponents(){
    JFrame loginFrame = new JFrame("Encrypted Chat - Login");
    loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    main loginPanel = new main();
    loginPanel.setLayout(new FlowLayout());
    loginFrame.setSize(300, 125);
    loginFrame.setResizable(false);
    loginFrame.setVisible(true);        
}
public static void main(String args[]){
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            initComponents();
        }
    });
}

}

EDIT: I know the password JTextField is meant to be a JPasswordField.. so ignore it :P

Andrei0427
  • 573
  • 3
  • 6
  • 18
  • Please, please don't preclude resizing a container unnecessarily; please use `setSize()` [sparingly](http://stackoverflow.com/q/7229226/230513); some platforms have different size fonts; some languages have different size words. Please do use `pack()`. – trashgod Sep 06 '12 at 10:37

4 Answers4

8

Two basic advices:

1.) When you use swing, and stuff doesnt show up/update, you should call JPanel.revalidate() and JPanel.repaint() These two functions will update your panel. If you are using a JFrame and you didn't add any extra panels to it, then you can get the content panel by JFrame.getContentPane()

2.) When you finished adding Components to a panel/frame you should also call pack() on the frame, this will ensure, that all your Components have the prefered size.

Balázs Édes
  • 13,452
  • 6
  • 54
  • 89
4

You never add your content to the JFrame. The minimal set of changes you need:

  public static void main(String args[]){
    final main main = new main();
    SwingUtilities.invokeLater(new Runnable(){
      public void run(){
        initComponents(main);
      }
    });
  }

And then modify initComponents to take a main object:

  public static void initComponents(main main){
    JFrame loginFrame = new JFrame("Encrypted Chat - Login");
    loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    main loginPanel = new main();
    loginPanel.setLayout(new FlowLayout());
    loginFrame.setSize(300, 125);
    loginFrame.setResizable(false);
    loginFrame.setVisible(true);
    loginFrame.add(main);  // <----- this line is added
  }
sjr
  • 9,769
  • 1
  • 25
  • 36
  • Is it possible to use the same instance of "main" which has been declared before the invokeLater() method inside the initComponents() method? Or do I need to create two instances by force? – Andrei0427 Sep 06 '12 at 07:49
  • @Andrei0427, yes. you can use the same instance. – shan Sep 06 '12 at 08:02
1

for built_in FlowLayout (for JPanel) I don't suggest to use pack() for JFrame, sure correct way could be to use proper and better LayoutManager for this job, GridBagLayout or SpringLayout

output by using JFrame#setSize() and without pack()

enter image description here

for example

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class MainLogin implements ActionListener {

    private JFrame loginFrame = new JFrame("Encrypted Chat - Login");
    private JPanel pnl = new JPanel();
    private JLabel userLabel;
    private JLabel passLabel;
    private JTextField userField;
    private JTextField passField;
    private JButton login;
    private JButton closeLogin;
    private JButton help;

    public MainLogin() {
        userLabel = new JLabel("Username: ");
        passLabel = new JLabel("Password: ");
        userField = new JTextField(16);
        passField = new JTextField(16);
        login = new JButton("Login");
        login.setActionCommand("login");
        login.setMnemonic(KeyEvent.VK_L);
        closeLogin = new JButton("Close");
        closeLogin.setActionCommand("closeLogin");
        closeLogin.setMnemonic(KeyEvent.VK_E);
        help = new JButton("Help");
        help.setActionCommand("helpLogin");
        help.setMnemonic(KeyEvent.VK_H);
        login.addActionListener(this);
        closeLogin.addActionListener(this);
        help.addActionListener(this);
        pnl.add(userLabel);
        pnl.add(userField);
        pnl.add(passLabel);
        pnl.add(passField);
        pnl.add(login);
        pnl.add(help);
        pnl.add(closeLogin);
        loginFrame.add(pnl);
        loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        loginFrame.setSize(300, 125);
        loginFrame.setResizable(false);
        loginFrame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                MainLogin mainLogin = new MainLogin();
            }
        });
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
0

Put JFrame.setVisible(true); on the last line after adding all components to it.

  • 1
    This was already done in the code provided in the original question (last operation in `initComponents()`), so this answer does not add anything. – Izruo May 06 '22 at 13:02
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 06 '22 at 19:16