Ошибка обновления Java Swing BasicUI, что я могу сделать? - PullRequest
0 голосов
/ 25 июня 2009

Моя программа использует Swing JPanel, JList, JScrollPane ...

Он работает нормально, но сгенерировал следующее сообщение об ошибке, и все же в сообщении не было сказано, какая строка моей программы вызвала ошибку, что я могу сделать?

=============================================== ==========================

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3

        at javax.swing.plaf.basic.BasicListUI.updateLayoutState(BasicListUI.java:1356)
        at javax.swing.plaf.basic.BasicListUI.maybeUpdateLayoutState(BasicListUI.java:1299)
        at javax.swing.plaf.basic.BasicListUI.getPreferredSize(BasicListUI.java:566)
        at javax.swing.JComponent.getPreferredSize(JComponent.java:1632)
        at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
        at java.awt.Container.layout(Container.java:1398)
        at java.awt.Container.doLayout(Container.java:1387)
        at java.awt.Container.validateTree(Container.java:1485)
        at java.awt.Container.validate(Container.java:1457)
        at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:670)
        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:127)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

=============================================== ======================================

У меня есть различные операторы .validate () и .repaint () в моей программе, чтобы убедиться, что она работает правильно. Поскольку моя программа выглядит нормально, значит ли это, что я могу игнорировать ошибку? Что я могу сделать, чтобы избежать сообщения об ошибке?

=============================================== ====================================== Вот более подробная информация:
<1> Java-версия jdk1.6.0_11
<2> Как мне начать список:

for (int Selector_Id=0;Selector_Id<6;Selector_Id++)
{
  Stock_Symbol_Data[Selector_Id]=new DefaultListModel();
  Stock_Symbol_List[Selector_Id]=new JList(Stock_Symbol_Data[Selector_Id]);
  Stock_Symbol_ScrollPane[Selector_Id]=new JScrollPane(Stock_Symbol_List[Selector_Id]);
}
...
Stock_Symbol_Data[A_Selector_Id].clear();

if (Selected_Symbols_Vector.size()>0)
  for (int i=0;i<Selected_Symbols_Vector.size();i++)
    Stock_Symbol_Data[A_Selector_Id].addElement(Selected_Symbols_Vector.elementAt(i));

Ишай прав, поскольку моей программе нужно создать очень длинный список, который занимает около минуты. Я не могу дождаться, чтобы увидеть пользовательский интерфейс, прежде чем инициализация будет завершена, поэтому я поместил его в класс "SwingWorker" и позволил ему выполнить инициализацию после открытия окна пользовательского интерфейса приложения; таким образом я могу видеть прогресс внутри пользовательского интерфейса, а не ждать, пока откроется первое окно. Мне кажется, что медлительность ПК мешает процессу обновления пользовательского интерфейса; если позже я перейду на более быструю машину, Swing должен исправить это, или я прав?

Я пытался использовать подход «(обернуть изменение в Runnable и вызвать SwingUtilities.invokeLater)», но он не сработал, как я ожидал. Он ждет, пока весь список не будет заполнен, затем открывает первое окно; это означает, что я должен посмотреть на пустой экран в течение одной минуты, прежде чем появится первый пользовательский интерфейс.

В SwingWorker теперь отображается случайное сообщение об ошибке - иногда здесь, иногда там, а иногда нет совсем.

Мой SwingWorker выглядит так:

class Update_Selection_Worker extends SwingWorker<Integer,Integer>             // Look into SwingWorkerDemo in Fit for details
{
  int Selector_Id;
  boolean Update_Only_This_Selector;
  Stock_Image_Scanner Stock_image_scanner;

  public Update_Selection_Worker(int Selector_Id,boolean Update_Only_This_Selector,Stock_Image_Scanner Stock_image_scanner)
  {
    this.Selector_Id=Selector_Id;
    this.Update_Only_This_Selector=Update_Only_This_Selector;
    this.Stock_image_scanner=Stock_image_scanner;
  }

  @Override
  protected Integer doInBackground() throws Exception
  {
//    Out("  In Update_Selection_Worker  Selector_Id="+Selector_Id);

    if (Update_Only_This_Selector)          // Only need to update from Rules_Panel_Id, eariler ones haven't changed
    {
      Stock_image_scanner.Update_Selector_List(Selector_Id);
      Thread.sleep(5);
      publish(Selector_Id);
    }
    else for (int i=Selector_Id;i<Stock_image_scanner.Rules_Panel_Count;i++)
    {
      Stock_image_scanner.Update_Selector_List(i);
      Thread.sleep(5);
      publish(i);
    }

    return 1;
  }

  @Override
  protected void process(java.util.List<Integer> chunks)                       // As the worker thread executes, it can publish results of V type. Override the process method to work with intermediate results.
  {
    for (final int i : chunks)
    {
      SwingUtilities.invokeLater(new Runnable()
      {
        public void run()
        {

          Stock_image_scanner.Selector_Total_Label[i].setText(Stock_image_scanner.Stock_Symbol_Data[i].getSize()+"");
          Stock_image_scanner.Stock_Symbol_List[i].revalidate();
          Stock_image_scanner.Stock_Symbol_List[i].repaint();
          Stock_image_scanner.Stock_Symbol_ScrollPane[i].revalidate();
          Stock_image_scanner.Stock_Symbol_ScrollPane[i].repaint();
          Stock_image_scanner.Selector_Panel[i].revalidate();
          Stock_image_scanner.Selector_Panel[i].repaint();

        }
      });
    }
  }

  @Override
  protected void done()
  {
  }

  public static void out(String message) { System.out.print(message); }
  public static void Out(String message) { System.out.println(message); }
}

Ответы [ 5 ]

4 голосов
/ 15 февраля 2014

Я думаю, что Ишай прав. У меня было похожее поведение, и я завернул его в ... EventQueue.invokeLater ... решил мою проблему.

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
        public void run() {
            listModel.addElement(book);
            jListBooks = new JList(listModel);
            jListBooks.setCellRenderer(new RobotBookListRenderer());
            jScrollPane1.setViewportView(jListBooks);
            jListBooks.updateUI();
        }
    });
3 голосов
/ 25 июня 2009

Очевидная причина для беспокойства заключается в том, что вы модифицируете свою Модель в другом потоке, а не в очереди событий Swing. Если это так, у вас есть проблема с вашим кодом, который вы должны решить (оберните изменения в Runnable и вызовите SwingUtilities.invokeLater, если ничего больше).

Если нет, я, конечно, видел случаи, когда вы просто видите ошибку свинга, и вам не стоит разбивать ваше приложение. Но, учитывая природу этой трассировки стека, я бы сказал, что это маловероятно, более вероятной причиной является многопоточность и очередь событий).

2 голосов
/ 26 июня 2009

Полагаю, что исключением также является то, что одновременная модификация некоторого массива объектов свинга.

SwingWorker имеет опцию «события в процессе». Вам необходимо переопределить защищенный метод process(List<V> chunks) и использовать метод void publish(V... chunks) для отправки обновления статуса в пользовательский интерфейс. В вашем случае обработки это означает периодически отправлять ваши частичные результаты, чтобы пользователю не было скучно.

0 голосов
/ 04 ноября 2016

У меня была эта проблема, и я понял, что:

  • если у вас есть объект JList
  • при вызове: listModel.removeAllElements ()
  • , а затем добавить элементы в listModel

это? Иногда? выполняет событие valueChanged.

Это может показаться случайным. Мой код был выполнен внутри SwingWorker. Решение НЕ в том, чтобы вызывать removeAllElements, а в том, чтобы создать новую ListModel.

Не делайте этого:

DefaultListModel listModel = (DefaultListModel) myJList.getModel (); listModel.removeAllElements ();

Сделайте это:

DefaultListModel listModel = new DefaultListModel (); myJList.setModel (ListModel); * * тысяча двадцать-один

Этот код иногда? выполняет метод valueChanged:

listModel.addElement (символ);

0 голосов
/ 25 июня 2009

Как вы настраиваете модель данных? Компоненту пользовательского интерфейса говорят, что у вас есть как минимум 4 элемента в dataModel, но в модели их не так много.

...