Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在多线程环境中重新绘制_Java_Multithreading_Swing_Applet_Event Dispatch Thread - Fatal编程技术网

Java 在多线程环境中重新绘制

Java 在多线程环境中重新绘制,java,multithreading,swing,applet,event-dispatch-thread,Java,Multithreading,Swing,Applet,Event Dispatch Thread,我正在开发一个小程序,其中包含大约10个不同的数据源(例如统计/错误日志/…)。每个数据源由单个网络连接更新,并通过观察者机制报告更新。小程序具有显示部分数据的不同视图。每个视图只对数据的某些部分感兴趣,并将自己注册为必要观察点的观察者 视图(扩展JPanel)主要由标准swing组件(例如JLabel、JButton等)组成。视图中组件的某些属性取决于来自底层数据模型的信息 例如: StatisticPanel::paintComponent(Graphics g) { clearStat

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

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

例如:

StatisticPanel::paintComponent(Graphics g) {
  clearStatisticButton.setEnabled(stat.hasEntries());
  minValueLabel.setText(stat.getMinValue());
  super.paintComponent(g);
}
此逻辑在StatisticPanel的
paintComponent()
方法中实现,而
update()
方法只调用repaint(),因为我不想在EDT之外操作组件


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

repaint()用于调用Swing RepaintManger,它反过来将安排组件的重新绘制,因此可以直接调用repaint。RepaitManager将确保在EDT上完成所有重新绘制。

我支持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

另外,请查看此线程:

+1以深入了解代码。更改组件的属性将导致重新绘制该组件。在某些情况下,这甚至可能会调用无限循环。有解决此类问题的最佳实践吗?因为如果我理解您的意思是正确的,Swingutiles.invokeLater方法在不执行paintComponent()代码中的程序逻辑的意义上更好,但也有可能导致无限循环。@tfk:请参见编辑1和编辑2