0

I ran into a problem with my code here that I am not able to explain. I have two Jframes, the first one has a button that when clicked it leads to the second frame. This works fine. But one problem is here: the second frame is first appearing as a skeleton, without the JComponents I added to it. It is waiting until all statements are executed that is when it paints the JComponents on the JFrame displayed skeleton.

Why is that so? How can I make it "fully display/paint" all the components before executing the next line of code?

Below is my code

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 *
 * @author JWizard
 */
public class Test {

    private JFrame frame;
    private JButton button;

    public Test() {
        initGUI();
        button.addActionListener((ActionEvent e) -> {
            JFrame frame1 = new JFrame("Second Jframe");
            frame1.setPreferredSize(new Dimension(300, 300));
            frame1.getContentPane().add(new JLabel("Swing Component"));
            frame1.pack();
            frame1.setVisible(true);
            frame1.setLocationRelativeTo(null);
            /**
             * After executing the above line,
             * 'frame1.setLocationRelativeTo(null);', I am expecting the program
             * to have fully "painted" my fame1 GUI, showing the label.
             */
            try {
                Thread.sleep(7000);
                System.out.println("statement 1");
                Thread.sleep(7000);
                System.out.println("statement 2");//after executing this statment thats when
                //the program paints the components of frame1
            } catch (InterruptedException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            }
        });

    }

    private void initGUI() {
        frame = new JFrame("Frame 1");
        button = new JButton("Go to Frame 2");
        frame.setLayout(new FlowLayout(FlowLayout.LEADING));
        frame.setPreferredSize(new Dimension(300, 300));
        frame.getContentPane().add(button);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);

    }

    public static void main(String[] args) {
        Test text = new Test();
    }

}
CN1002
  • 1,115
  • 3
  • 20
  • 40
  • You're blocking the event dispatch thread which handles the repainting of the UI etc. – Thomas Sep 05 '17 at 09:37
  • @Thomas Where am I blocking it? – CN1002 Sep 05 '17 at 09:40
  • 3
    "Where am I blocking it?" `Thread.sleep(7000);` Here. – Fildor Sep 05 '17 at 09:40
  • 1
    Your actionlistener etc. all run in the EDT so as Filder wrote your sleep statements are blocking it. Read up on the EDT and workers/tasks on how to handle long running actions without blocking the EDT. – Thomas Sep 05 '17 at 09:43
  • @Thomas If I comment those lines, it is still behaving the same...it is waiting until `statment 2`. I put the `Thread.sleep(7000);` to introduce some waiting time to see that it is delaying in painting – CN1002 Sep 05 '17 at 09:46
  • 3
    Of course it is still the same as those statements are executed on the same thread. Repainting will only happen _after_ the listener has finished running. – Thomas Sep 05 '17 at 09:50
  • @Thomas Good....the ` after the listener has finished running` has done it. How can I solve this? I tried using `Threads` but got the same response...I was guessing it could be the problem when I used threads. – CN1002 Sep 05 '17 at 09:55
  • 1
    "I tried using Threads" - well it depends on what you've tried but as I said, have a look at any tutorial on this topic or even the JavaDoc on `SwingWorker`. – Thomas Sep 05 '17 at 09:59
  • 1
    See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) – Andrew Thompson Sep 05 '17 at 10:07

1 Answers1

1

Give this a try:

public Test() {
        initGUI();
        button.addActionListener((ActionEvent e) -> {
            JFrame frame1 = new JFrame("Second Jframe");
            frame1.setPreferredSize(new Dimension(300, 300));
            frame1.getContentPane().add(new JLabel("Swing Component"));
            frame1.pack();
            frame1.setVisible(true);
            frame1.setLocationRelativeTo(null);

            new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    try {
                        Thread.sleep(7000);
                        System.out.println("statement 1");
                        Thread.sleep(7000);
                        System.out.println("statement 2");
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    return null;
                }
            }.execute();
        });

}
Phil
  • 306
  • 1
  • 8