【问题标题】:Why is the painting of a component delayed?为什么组件的绘制延迟?
【发布时间】:2023-03-10 14:46:01
【问题描述】:

我想将面板涂成蓝色,然后等待 5 秒钟,然后执行其他操作。
现在我有了以下代码,我希望它可以做我想做的事。这里是:

JPanel somePanel = getSomePanel();
somePanel.setBackground(Color.BLUE);
Object lock = new Object();
synchronized (lock) {
    try {
        lock.wait(5000);
    }
    catch (InterruptedException exc) { }
}
// Do other stuff

但是,它会等待五秒钟,然后将组件涂成蓝色。

  • 为什么要先等待,然后画蓝色,而不是反过来? (我猜这与 Swing 机制有关...?)
  • 如何“更改订单”?

【问题讨论】:

  • 不要阻塞 EDT(事件调度线程)——当这种情况发生时,GUI 将“冻结”。而不是调用 Thread.sleep(n) 实现 Swing Timer 用于重复任务或 SwingWorker 用于长时间运行的任务。有关详细信息,请参阅Concurrency in Swing
  • @AndrewThompson 但这对我来说很好,不使用 invokeLater()invokeAndWait() 这种行为也取决于不同的平台?
  • “取决于不同的平台?” 平台、JRE、时间、湿度.. 不在 EDT 上进行 GUI 编辑会导致“不可预测”的行为。当然,阻塞EDT的结果是非常可预测的。
  • 另见this类似的答案和variation
  • @AndrewThompson:别忘了 Look & Feel。我记得这个,因为我以前被它烧过!

标签: java multithreading swing awt event-dispatch-thread


【解决方案1】:

不要在 GUI 事件处理程序中等待 - 它会阻止处理消息,例如。重绘请求。

当您等待锁定时,GUI 不会执行任何操作。

【讨论】:

    【解决方案2】:

    不要通过锁定 Swing 事件线程来执行同步代码,因为您所做的只是锁定 Swing 本身并冻结 GUI。谷歌“Concurrency in Swing”了解详情。我自己我会为此使用Swing Timer。请注意,您的帖子使用了 标签,但您实际上并没有在任何地方进行多线程处理。

    【讨论】:

    【解决方案3】:

    其他的都是对的,如果你在事件派发线程上等待,那么这个线程在此期间不会做任何绘画。

    不过,有一个技巧可以在不启动新线程的情况下帮助您:在设置背景颜色后调用 paintImmediately

    somePanel.paintImmediately(0, 0, somePanel.getWidth(), somePanel.getHeight());
    

    【讨论】:

      猜你喜欢
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多