我的问题很简单,代码很复杂,答案不是那么容易找到,所以我寻求帮助。
我正在编写一个多线程应用程序,它是这样工作的:
1)一个线程正在读取文件并从文本文件中解析信息(每 500 毫秒尝试到达文件末尾)
2)当找到相关信息时,线程将其存储并通知作为观察者的控制器
3)当通知控制器时,它通知另一个线程(GUI)更新我想向用户显示的信息。
除非我打电话revalide()
或出现异常,因为 GUI 更新得太频繁了validate()
。repaint()
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: No such child: 7
at java.awt.Container.getComponent(Container.java:323)
at javax.swing.JComponent.rectangleIsObscured(JComponent.java:4393)
at javax.swing.JComponent.paint(JComponent.java:1052)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5206)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1493)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1424)
at javax.swing.RepaintManager.paint(RepaintManager.java:1217)
at javax.swing.JComponent._paintImmediately(JComponent.java:5154)
at javax.swing.JComponent.paintImmediately(JComponent.java:4964)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:781)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:739)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:688)
at javax.swing.RepaintManager.access$700(RepaintManager.java:59)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1632)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:660)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
我考虑过运行另一个线程,每 500 毫秒可能会尝试revalidate()
使用 GUI,但可能有更好的选择。有什么我应该担心的,比如在我调用之前停止 GUI 线程revalidate()
然后恢复它或类似的东西?
是的,我确实从面板中删除了组件(JLabels),用新数据替换它们。我会试试你说的。
顺便说一句,invokelater 和 start like another thread 有很大区别吗?
解决方案 :
我创建了一个如下所示的方法:
protected void updateGUI(final Param param1, final Param param2){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//write your code
param1.validate();
param1.repaint();
}
});