简体   繁体   中英

Thread.sleep and repainting

I have a panel that displays text. I want the panel to change its text and then have the application pause before anything else happens. I'm using Thread.sleep(1000). For some reason, though, the application doesn't finish painting the panel before Thread.sleep gets called (the text doesn't get changed). I also tried this:

board.invalidate();
board.setLeftMessage("Not");
board.setRightMessage("Here");
board.revalidate();
Date current = new Date();
long timeNow = current.getTime();
Date newDate = new Date(timeNow + 1000);
while (current.before(newDate))
    current = new Date();

but no luck there either. Anyone have a suggestion? Thanks so much.

You are blocking the AWT Event Dispatch Thread (EDT). The EDT handle repainting and input events, so your code need not be multithreaded (which would be effectively impossible). Use javax.swing.Timer to send an event later on the EDT. (Do not confuse javax.swing.Timer with java.util.Timer !)

Take a look at javax.swing.Timer - I think this is what you'll need to accomplish this.

EDIT #1: The Sun\\Oracle documentation actually suggests using Swing Timers from here .

In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing.

EDIT #2: It looks like there are some good basic tutorials here .

EDIT #3: Removed suggestion of using TimerTask - in this case it would be a bad idea.

Your "long running task" needs to run in a separate Thread. Then when you want to update the GUI you need the code to run on the Event Dispatch Thread (EDT). Then you can ask the separate Thread to sleep and it won't affect the painting of the GUI.

You should be able to use a SwingWorker for this. Read the section from the Swing tutorial on Concurrency for more information.

If you don't like using the SwingWorker, then you need to create your own Thread and wrap the code that updates the GUI in a SwingUtilities.invokeLater().

Thread.sleep is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.

As a result when the EDT comes out of the sleep phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.

To correct the situation use a timer which triggers periodically after specific intervals of time.

You shouldn't be updating GUI components from your main thread. Use SwingUtilities.invokeLater to schedule your update on the event thread:

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    board.invalidate();
    board.setLeftMessage("Not");
    board.setRightMessage("Here");
    board.revalidate();
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM