Search code examples
javaeclipsejframedisplaydispose

Display and then close a frame in Java


Here the code:

public class attrape_ball {
    JFrame frame = new JFrame();
    JPanel attrape = new JPanel();
    
    public attrape_ball(pokeball pk) {
    JLabel ramasseball = new JLabel("vous avez ramasser ");
    attrape.add(ramasseball);
        
    frame.setSize(200,100);
    frame.add(attrape); 
    frame.setVisible(false);
    }
    
    @Override
    public void afficherJframe() {
    frame.setVisible(true);
    try {
    Thread.sleep(3000);
    } catch (InterruptedException e) {
    e.printStackTrace();}
    frame.dispose();
    }
}

When I call the function afficherJFrame() I want to display the JLabel then wait 3 sec and then close the JFrame. When I run it, the JLabel isn't displayed. That is the problem. (The JFrame is closed 3 sec later as I want).


Solution

  • Swing is single threaded and not thread safe. This means that you can't perform long running or blocking operations (like Thread.sleep) within the context of the Event Dispatching Thread. It also means that you shouldn't update the UI or any state the UI relies on from outside the context of the Event Dispatching Thread.

    See Concurrency in Swing for more details.

    Essentially, the Thread.sleep is likely preventing the window from been painted.

    Instead, use a Swing Timer, for example...

    import java.awt.EventQueue;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.border.EmptyBorder;
    
    public class Main {
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(new GridBagLayout());
                setBorder(new EmptyBorder(32, 32, 32, 32));
    
                JButton btn = new JButton("Show me the money");
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JFrame popup = new JFrame();
                        JLabel label = new JLabel("Money");
                        label.setBorder(new EmptyBorder(32, 32, 32, 32));
                        popup.add(label);
                        popup.pack();
                        popup.setLocationRelativeTo(TestPane.this);
                        popup.setVisible(true);
                        Timer timer = new Timer(3000, new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                popup.dispose();
                            }
                        });
                        timer.setRepeats(false);
                        timer.start();
                    }
                });
                add(btn);
            }
    
        }
    }
    

    See How to Use Swing Timers for more details