繁体   English   中英

在多线程环境中重绘

[英]Repainting in a multithreaded environment

我正在开发一个带有大约十个不同数据源(例如统计/错误日志/...)的小程序。 每个数据源由单个网络连接更新,并通过观察者机制报告更新。 小程序具有显示部分数据的不同视图。 每个视图只对数据的某些部分感兴趣,并在必要的 Observables 上将自己注册为观察者。

视图(扩展的 JPanel)主要由标准的 swing 组件(例如 JLabels、JButton、...)组成。 视图中组件的某些属性取决于来自底层数据 model 的信息。

例子:

StatisticPanel::paintComponent(Graphics g) {
  clearStatisticButton.setEnabled(stat.hasEntries());
  minValueLabel.setText(stat.getMinValue());
  super.paintComponent(g);
}

此逻辑在 StatisticPanel 的paintComponent()方法中实现,而update()方法只调用 repaint(),因为我不希望在 EDT 之外操作组件。

这是在多线程环境中更新 swing 组件的预期方式吗? 将 Runnable 与SwingUtitlies.invokeLater()一起使用会更好吗? 有没有更好的方法来解决这个问题?

我第二个camickr的建议,但关于这个代码片段:

StatisticPanel::paintComponent(Graphics g) {
  clearStatisticButton.setEnabled(stat.hasEntries());
  minValueLabel.setText(stat.getMinValue());
  super.paintComponent(g);
}

您的 paintComponent 方法(前两种方法)中有非绘画方法,这不应该是 1)您希望此方法尽可能精简和快速,因此只有与绘画相关的代码,以及 2)您无法绝对控制何时调用此方法或即使调用此方法,因此非绘画相关的代码和程序逻辑不属于其中。 出于这些原因,我强烈建议您将它们从那里删除,而是应该与paintComponent 分开调用,但与 EDT 上的大多数 Swing 代码一样。

编辑 1
我不是专业人士,但如果你给你的 StaticPanel 一个类似的方法怎么样:

   public void doMyUpdate() {
      if (SwingUtilities.isEventDispatchThread()) {
         clearStatisticButton.setEnabled(stat.hasEntries());
         minValueLabel.setText(stat.getMinValue());
      } else {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               clearStatisticButton.setEnabled(stat.hasEntries());
               minValueLabel.setText(stat.getMinValue());
            }
         });
      }
      repaint(); // if the paintComponent method has more than just a super call.
   }

编辑 2
另外,请看一下这个线程: check-if-thread-is-edt-is-necessary

repaint() 用于调用 Swing RepaintManger 反过来会安排组件的重绘,所以是的,直接调用 repaint 是可以的。 RepaintManager 将确保在 EDT 上完成所有重绘。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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