【问题标题】:Java Swing BasicUI update error, what can I do?Java Swing BasicUI 更新报错,怎么办?
【发布时间】:2009-06-25 19:35:07
【问题描述】:

我的程序使用 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() 语句,以确保它正确运行。因为我的程序看起来不错,这是否意味着我可以忽略错误?我能做些什么来避免错误消息?

================================================ ======================================= 这里有更多细节:
Java版jdk1.6.0_11
我如何初始化列表:

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

Yishai 是对的,因为我的程序需要初始化一个很长的列表,大约需要一分钟。我迫不及待地想在初始化完成之前看到 UI,所以我把它放在一个“SwingWorker”类中,让它在应用程序 UI 窗口打开后进行初始化;这样我就可以从 UI 中看到进度,而不是等待第一个窗口打开。在我看来,是 PC 的缓慢导致了 UI 更新过程的混乱;如果我以后换一台速度更快的机器,Swing 应该会解决这个问题,还是我说得对?

我尝试使用“(将更改包装在 Runnable 中并调用 SwingUtilities.invokeLater)”方法,但它没有按我预期的那样工作。它等到所有列表都填写完毕,然后打开第一个窗口;这意味着我必须在第一个 UI 出现之前查看空白屏幕一分钟。

使用 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); }
}

【问题讨论】:

  • 您能发布创建/初始化您的 JList 的代码吗?
  • 永远不要忽略 Java 向您抛出的错误(或任何编程语言)。您可能不会注意到任何错误,但通常像这样的错误会引起关注,并且可能会影响您的未来。最好现在就在你头脑清醒的时候处理它,而且你还没有在上面写很多代码。
  • 你用的是哪个版本的java?
  • 在多线程处理时出现随机错误是您做错了的明确信号。你能发布 SwingWorker 吗?

标签: java multithreading swing swingworker


【解决方案1】:

我认为一晒是对的。我有类似的行为并将其包装到 ...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();
        }
    });

【讨论】:

    【解决方案2】:

    这里引起关注的明显原因是您在不同的线程中修改模型,而不是在 Swing 事件队列中。如果是这种情况,您的代码确实有问题需要解决(将更改包装在 Runnable 中,如果没有其他问题,请调用 SwingUtilities.invokeLater)。

    如果不是这样,我肯定见过这样的情况,您只是看到了一个摆动错误并且不值得让您的应用程序崩溃。但鉴于此堆栈跟踪的性质,我会说这不太可能,更可能的原因是线程和事件队列)。

    【讨论】:

      【解决方案3】:

      我猜也是例外是因为一些swing对象数组的并发修改。

      SwingWorker 可以选择“进行中的事件”。您需要覆盖 process(List&lt;V&gt; chunks) protected 方法并使用 void publish(V... chunks) 方法将状态更新发送到 UI。在您的处理案例中,这意味着定期提交您的部分结果,以免用户感到无聊。

      【讨论】:

      • 是的,你说的很对,虽然我一直在使用 SwingWorker,但我从来没有使用过 publish() 和 process() 方法,这是第一次学习如何使用它。
      【解决方案4】:

      您如何设置数据模型? UI 组件被告知您在 dataModel 中至少有 4 个项目,但模型没有那么多。

      【讨论】:

        【解决方案5】:

        我遇到了这个问题,只是想通了:

        • 如果你有一个 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(symbol);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多