Исключение в потоке при обновлении графического интерфейса - PullRequest
2 голосов
/ 13 февраля 2011

Моя проблема проста, код сложен, и ответ не так легко найти, поэтому я прошу помощи.

Я программирую многопоточное приложение, вот как оно работает:

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();
        }
    });

1 Ответ

2 голосов
/ 13 февраля 2011

Мне кажется, что исключение похоже на то, что происходит с GUI за пределами EDT, что все портит: более конкретно, компонент, кажется, удаляется, а графический интерфейс хочет его перекрасить.

Постарайтесь, чтобы код, который добавляет / удалял компоненты, передавался как Runnable в SwingUtilities.invokeLater(), чтобы обеспечить синхронизацию всего, что каким-либо образом изменяет графический интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...