Thread.sleep 和重画
我有一个显示文本的面板。我希望面板更改其文本,然后在发生其他情况之前让应用程序暂停。我正在使用 Thread.sleep(1000)。但由于某种原因,应用程序在调用 Thread.sleep 之前没有完成面板的绘制(文本没有更改)。我也尝试过这个:
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();
但也没有运气。有人有建议吗? 非常感谢。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您正在阻止 AWT 事件调度线程 (EDT)。 EDT 处理重画和输入事件,因此您的代码不需要是多线程的(这实际上是不可能的)。稍后使用 javax.swing.Timer 在 EDT 上发送事件。 (不要将
javax.swing.Timer
与java.util.Timer
混淆!)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 confusejavax.swing.Timer
withjava.util.Timer
!)看一下
javax.swing.Timer
- 我认为这就是您完成此任务所需的。编辑 #1:Sun\Oracle 文档实际上建议使用 此处< /a>.
编辑#2:看起来有一些很好的基本教程这里。
编辑 #3:删除了使用 TimerTask 的建议 - 在这种情况下这将是一个坏主意。
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.
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.
您的“长时间运行的任务”需要在单独的线程中运行。然后,当您想要更新 GUI 时,您需要在事件调度线程 (EDT) 上运行代码。然后你可以让单独的线程休眠,它不会影响GUI的绘制。
您应该能够为此使用 SwingWorker。有关详细信息,请阅读 Swing 教程中有关并发的部分。
如果您不喜欢使用 SwingWorker,那么您需要创建自己的线程并将更新 GUI 的代码包装在 SwingUtilities.invokeLater() 中。
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().
您不应该从主线程更新 GUI 组件。使用
SwingUtilities.invokeLater
在事件线程上安排更新:You shouldn't be updating GUI components from your main thread. Use
SwingUtilities.invokeLater
to schedule your update on the event thread:Thread.sleep
是一个长时间运行的任务。当您在 EDT 中运行此类任务时,它会阻止所有重绘请求的执行。所有待处理的重绘请求和在睡眠阶段发送的重绘请求都会排队等待将来处理。因此,当 EDT 退出睡眠阶段时,它会将所有此类重绘请求(如果启用了默认属性的合并)合并为一个要执行的重绘。如果未启用合并,则所有排队的请求都会串行执行,中间没有任何时间间隔。结果似乎 UI 没有更新。
要纠正这种情况,请使用
计时器
,该计时器会在特定时间间隔后定期触发。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.