Pregunta

Mi programa usa Swing JPanel, JList, JScrollPane...

Funciona bien, pero generó el siguiente mensaje de error y, aún así, en el mensaje no decía qué línea de mi programa causó el error, ¿qué puedo hacer?

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

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)

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

Tengo varias declaraciones .validate() y .repaint() en mi programa para asegurarme de que se ejecute correctamente.Debido a que mi programa se ve bien, ¿eso significa que puedo ignorar el error?¿Algo que pueda hacer para evitar el mensaje de error?

==================================================== =================================== Aquí hay más detalles:
<1> Versión de Java jdk1.6.0_11
<2> Cómo inicio la lista:

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 tiene razón, ya que mi programa necesita iniciar una lista muy larga, lo que requiere aproximadamente un minuto.No puedo esperar a ver la interfaz de usuario antes de que finalice el inicio, así que la puse en una clase "SwingWorker" y dejo que realice el inicio después de que se abra la ventana de la interfaz de usuario de la aplicación;de esa manera puedo ver el progreso desde la interfaz de usuario en lugar de esperar a que se abra la primera ventana.Me parece que es la lentitud de la PC la que está arruinando el proceso de actualización de la interfaz de usuario;Si luego paso a una máquina más rápida, Swing debería solucionar este problema, ¿o tengo razón en esto?

Intenté utilizar el enfoque "(envolver el cambio en un Runnable y llamar a SwingUtilities.invokeLater)", pero no funcionó como esperaba.Espera hasta que se complete toda la lista y luego abre la primera ventana;eso significa que tengo que mirar la pantalla vacía durante un minuto antes de que aparezca la primera interfaz de usuario.

Con SwingWorker, ahora muestra el mensaje de error aleatoriamente: a veces aquí, a veces allí, otras veces no.

Mi SwingWorker se ve así:

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); }
}
¿Fue útil?

Solución

Supongo que también la excepción se debe a la modificación simultánea de alguna matriz de objetos oscilantes.

SwingWorker tiene la opción de "eventos en curso".Necesitas anular process(List<V> chunks) método protegido y utilizar el void publish(V... chunks) Método para enviar actualizaciones de estado a la interfaz de usuario.En su caso de procesamiento, esto significa enviar sus resultados parciales periódicamente para que el usuario no se aburra.

Otros consejos

Creo que Yishai tiene razón. Tuve un comportamiento similar y envolviéndolo en ... EventQueue.invokeLater ... resolvió mi problema.

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

La causa obvia de preocupación aquí es que modifica su Modelo en un hilo diferente, y no en la cola de eventos Swing. Si ese es el caso, tiene un problema con su código que debe abordar (envuelva el cambio en un Runnable y llame a SwingUtilities.invokeLater si nada más).

Si no, ciertamente he visto casos en los que solo ves un error de swing y no vale la pena bloquear tu aplicación. Pero dada la naturaleza de este seguimiento de la pila, diría que no es probable, la causa más probable es el subproceso y la cola de eventos).

¿Cómo está configurando su modelo de datos? Se le dice al componente de la interfaz de usuario que tiene al menos 4 elementos en el modelo de datos, pero el modelo no tiene tantos.

Tuve este problema y descubrí que:

  • si tiene un objeto JList
  • cuando llamas: listModel.removeAllElements ()
  • y luego agregue elementos al listModel

¿a veces? ejecuta el evento valueChanged.

Esto puede parecer aleatorio. Mi código se ejecutó dentro de SwingWorker. La solución NO es llamar a removeAllElements sino crear un nuevo ListModel.

No hagas esto:

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

Haz esto:

DefaultListModel listModel = new DefaultListModel (); myJList.setModel (listModel);

Este código? a veces? ejecuta el método valueChanged:

listModel.addElement (símbolo);

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top