2013-04-17 1 views
-1

Это был бы мой первый вопрос в StackOverflow, но, конечно, не первый раз это было полезно. Однако я не стал больше пытаться найти различные возможные решения, которые я нашел до сих пор.java.lang.NullPointerException при быстром обновлении JList

В настоящее время я выполняю стажировку и создаю утилиту для визуализации информации, считываемой через интерфейс USB-to-CAN - «сеть контроллеров». Проще говоря: он считывает сообщения с CAN-разъема на встроенной системе. Каждое сообщение состоит из поля идентификатора (содержащего адрес источника, адрес назначения, идентификатор и т. Д.) + 8 максимальных байтов данных. Эти поля преобразуются в строки, и я хочу добавлять их в JList каждый раз при получении нового сообщения. JList 'log_listview' инициализируется новой версией DefaultListModel 'listModel', и она добавляется в Can_Panel, ContentPane. Чтение происходит в отдельном потоке с именем «vci_thread», который инициализируется и запускается сразу после создания панели.

Чтение начинается только через 5 секунд, время, необходимое для инициализации интерфейса USB-to-CAN. На первый взгляд, JList хорошо работает. Каждое полученное сообщение правильно добавлено в listModel, и я даже не заметил, что были ошибки, потому что программа просто продолжается без отсутствующих элементов, автоматической прокрутки и автоматического удаления первого элемента, когда listModel.size()> 99 ...

Теперь и тогда я получаю следующее сообщение об ошибке («Размер: #» является отладочный вывод фактического числа элементов в JList):

Size: 60 
Size: 61 
Size: 62 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at javax.swing.BufferStrategyPaintManager.flushAccumulatedRegion(Unknown Source) 
    at javax.swing.BufferStrategyPaintManager.endPaint(Unknown Source) 
    at javax.swing.RepaintManager.endPaint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Size: 63 
Size: 64 
Size: 65 
Size: 66 

Кроме того, когда много сообщений приходят быстро, я регулярно получаю следующую ошибку. Я считаю, что это что-то делать с удалением первого индекса, так как размер в настоящее время 100:

Size: 100 
Size: 100 
Size: 100 
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 99 >= 99 
    at java.util.Vector.elementAt(Unknown Source) 
    at javax.swing.DefaultListModel.getElementAt(Unknown Source) 
    at javax.swing.plaf.basic.BasicListUI.paintCell(Unknown Source) 
    at javax.swing.plaf.basic.BasicListUI.paintImpl(Unknown Source) 
    at javax.swing.plaf.basic.BasicListUI.paint(Unknown Source) 
    at javax.swing.plaf.ComponentUI.update(Unknown Source) 
    at javax.swing.JComponent.paintComponent(Unknown Source) 
    at javax.swing.JComponent.paint(Unknown Source) 
    at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
    at javax.swing.BufferStrategyPaintManager.paint(Unknown Source) 
    at javax.swing.RepaintManager.paint(Unknown Source) 
    at javax.swing.JComponent._paintImmediately(Unknown Source) 
    at javax.swing.JComponent.paintImmediately(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at javax.swing.RepaintManager$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
    at javax.swing.RepaintManager.access$1000(Unknown Source) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
    at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$200(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Size: 100 
Size: 100 

Вот код, который выполняется после того, как новое сообщение CAN считывается и байты были преобразованы в строки :

// Add a new element containing the strings: 
    listModel.addElement(counter + ": " + src_addr_hex + " " + dest_addr_hex + " - " + predef_hex + " - " + str_data); 

    // Auto scroll down after the element has been added 
    if (listModel.size()-1 >= 0) { 
     try { 
      log_listview.ensureIndexIsVisible(listModel.size()-1); 
     } catch (Exception ex) { 
     // 
     } 
    } 

    // When listModel contains 100 elements, remove the first index 
    if (listModel.size()>99) { 
     listModel.remove(0); 
    } 

Это показание, вместе с этим код выполняется внутри, а() петли и включает в себя Thread.sleep (1) каждый раз, чтобы ограничить использование центрального процессора. Я убедил с try {} catch(), что, когда нет нового сообщения для чтения, преобразование строки и добавление в JList просто пропущены. Когда сообщения поступают быстрее, чем один цикл этого цикла, они просто кэшируются и обрабатываются один за другим, пока в конце концов моя программа не догонит. Это довольно обширный вопрос, но я надеюсь, что он сможет мне помочь.

Обновление: Я переместил код в новый runnable 'update_JList' и назвал его методом SwingUtilities.invokeLater сразу после прочтения строки. Я не получаю никаких ошибок, и здорово видеть, насколько плавные обновления графического интерфейса. Тем не менее, в настоящее время я столкнулся с другой проблемой дубликатов или недостающие элементы в JList:

Screenshot

Слева находится отладочный вывод, показывающий каждое входящее сообщение по одному. Справа находится JList, отображающий сообщение с адресом источника 45 14 раз.

+0

a) убедитесь, что обновление списка происходит на EDT. B) при условии, что обеспечение выполняется в listDataListener, убедитесь, что оно происходит _after_, список готов с любым внутренним обновлением, которое завершает ваш код в invokeLater – kleopatra

+0

что-то неправильное в коде, который вы не показываете ... заметьте, мы не можем прочесть ваш код, по крайней мере, на расстоянии ;-) Показать SSCCE, который демонстрирует проблему – kleopatra

+0

В настоящее время я не могу придумать SSCCE для тиражирования проблема, и я боюсь, что вам понадобится интерфейс USB-to-CAN и та же встроенная система для тестирования с помощью :) Проблема дубликатов, по-видимому, решена путем установки логического состояния после чтения нового сообщения CAN и сброса это сразу после добавления элемента. Только время от времени один элемент отсутствует по сравнению с выходом отладки, хотя между этими двумя строками нет кода: System.out.println («Строки»); & SwingUtilities.invokeLater (update_JList); –

ответ

1

Чтение происходит в отдельном потоке под названием «vci_thread», который инициализируется и запускается сразу после создания панели.

Обновления GUI должны выполняться на EDT, а не на отдельной теме.Прочтите раздел из руководства Swing по телефону Concurrency для получения дополнительной информации.

Вы можете использовать SwingWorker или если вы хотите продолжить использовать существующий поток, тогда вам нужно будет использовать SwingUtilities.invokeLater() всякий раз, когда вы хотите обновить модель.