orohev
orohev

Reputation: 73

Java Swing making the thread wait once

I'm trying to make my GUI wait for 2 seconds after a recent update in the graphics. It means that after I use:

    boardLogo.repaint();
    boardLogo.revalidate();

I want the GUI to wait before making further computations and then paint them again.

The code:

        SwingUtilities.invokeLater(new Runnable() {
            @SuppressWarnings("rawtypes")
            @Override
            public void run() {
                SwingWorker swingWorkerExample = new SwingWorker(){
                    @Override
                    protected Object doInBackground() throws Exception {
                        return null;
                    }
                    protected void done(){
                        try {
                            Thread.sleep(2000); //wait 2 seconds.
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                swingWorkerExample.execute();
            }
        });
        //.... more code here
        boardLogo.repaint();
        boardLogo.revalidate();

But when I run it - first it executes the last two lines, then waits for 2 seconds...

To be honest, my knowledge about Threads and Java Swing is not the best (especially when it comes to understanding swing worker, which I've tried to read about from Oracle site), so I would appreciate it if the answer will be detailed.

Thanks!

Upvotes: 0

Views: 616

Answers (1)

Solomon Slow
Solomon Slow

Reputation: 27115

when I run it - first it executes the last two lines, then waits for 2 seconds ... my knowledge about Threads and Java Swing is not the best.

You say, it executes the last two lines. Ever stop to wonder what it is?

It is a thread. Threads are what execute code in a Java program, and every line that gets executed is executed by some thread.

When your code calls invokeLater(), it is submitting a task (i.e., a piece of code) to be executed by Swing's event dispatch thread (EDT); and when your code calls swingWorker.execute() it is submitting a task to be performed by one of Swing's background threads.

The whole point of having more than one thread in a program is that they can be doing different things at the same time.

In your case, you've got the EDT sleeping for two seconds while, at the same time, some other thread is calling boardLogo.repaint(); and boardLogo.revalidate();


There's a couple of important things to know about Swing and multi-threading:

  • All of your event handlers will be run by the EDT.

  • An event handler should never do anything that takes more than a small fraction of a second, because your application will not be able to respond to any other events (i.e., it will appear to be "hung") until the handler returns.

  • No other thread is allowed to interact with any of Swing's GUI components.

One important use-case for invokeLater() is, it's how code running in the background thread can communicate with GUI components. invokeLater() submits a task (i.e., a piece of code) that will be run in the EDT.

The main use-case for SwingWorker is pretty much the opposite of that: It's how an event handler, running in the EDT, can kick off a task that is going to take more than a small fraction of a second to complete.


You can learn about this stuff by working your way through the Swing Concurrency tutorial: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/

Upvotes: 2

Related Questions