Моя проблема проста, код сложен, и ответ не так легко найти, поэтому я прошу помощи.
Я программирую многопоточное приложение, вот как оно работает:
1) Один поток читает файл и анализирует информацию из текстового файла (каждые 500 миллисекунд пытается достичь конца файла)
2) Когда соответствующая информация найдена, поток сохраняет ее и уведомляет контроллер, который является наблюдателем
3) Когда контроллер уведомляется, он уведомляет другой поток (GUI), который обновляет информацию, которую я хотел бы показать пользователю.
За исключением случаев, когда я звоню revalide()
или 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 и запуском как другой поток?
Решение:
Я создал метод, который выглядит следующим образом:
protected void updateGUI(final Param param1, final Param param2){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//write your code
param1.validate();
param1.repaint();
}
});