Thread.sleep 和重画

发布于 2024-10-06 02:31:12 字数 446 浏览 5 评论 0原文

我有一个显示文本的面板。我希望面板更改其文本,然后在发生其他情况之前让应用程序暂停。我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

零時差 2024-10-13 02:31:12

您正在阻止 AWT 事件调度线程 (EDT)。 EDT 处理重画和输入事件,因此您的代码不需要是多线程的(这实际上是不可能的)。稍后使用 javax.swing.Timer 在 EDT 上发送事件。 (不要将 javax.swing.Timerjava.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 confuse javax.swing.Timer with java.util.Timer!)

仙女山的月亮 2024-10-13 02:31:12

看一下 javax.swing.Timer - 我认为这就是您完成此任务所需的。

编辑 #1:Sun\Oracle 文档实际上建议使用 此处< /a>.

一般情况下,我们推荐使用Swing
定时器而不是通用
GUI 相关任务的计时器,因为
Swing 定时器都有相同的特点,
预先存在的计时器线程和
自动执行 GUI 相关任务
在事件分派线程上执行。
但是,您可以使用
通用定时器,如果你不这样做
计划从以下位置接触 GUI
定时器,或者需要执行较长时间
处理。

编辑#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.

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.

清晰传感 2024-10-13 02:31:12

您的“长时间运行的任务”需要在单独的线程中运行。然后,当您想要更新 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().

你不是我要的菜∠ 2024-10-13 02:31:12

您不应该从主线程更新 GUI 组件。使用 SwingUtilities.invokeLater 在事件线程上安排更新:

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

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();
  }
};
怀中猫帐中妖 2024-10-13 02:31:12

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文