JMS Queue to JTable Update [Ahora obteniendo una excepción después de los cambios]

StackOverflow https://stackoverflow.com/questions/1624679

  •  06-07-2019
  •  | 
  •  

Pregunta

Estoy escribiendo mi propio navegador JMS y estoy sorprendido por la actualización de JTable de Mensajes desde los servidores JMS. He intentado AbstractTableModel TableModelListener para actualizar Jtable cuando se agregan los datos en LinkedList. Este logis a continuación funciona, pero no se actualiza en tiempo real, significa que quisiera mostrar todas y cada una de las filas agregadas a Jtable inmediatamente cuando se agrega de QueueBrowser a LinkedList.

He actualizado el código según las sugerencias a continuación.

¿Estoy haciendo algo mal? ¿Alguien me puede ayudar?

QueueBrowser qb = session.createBrowser(q);
MsgTable mt = (MsgTable) queueTable.getModel();
mt.load(qb.getEnumeration(),mt);
qb.close();




 class MsgTable extends AbstractTableModel implements TableModelListener{


      final String[] columnNames = { "#", "Timestamp", "Type", "Mode",
        "Priority" };

      public void setRowSize(){

      }
      LinkedList queueList = new LinkedList();

      public int getRowCount() { if (queueList == null) { return 0; } else { return queueList.size();}}
      public int getColumnCount() { return columnNames.length;}
      public String getColumnName(int column) {return columnNames[column];}

      public Object getValueAt(int row, int column) {
       if(queueList == null){
        return null;
       }
                        Message m = (Message) queueList.get(row);
                        ...  
      }

      void load(Enumeration e,MsgTable mt) {
                         mt.addTableModelListener(this);
        while(e.hasMoreElements()){
         queueList.add(e.nextElement());

        }
                      fireTableDataChanged();   
      }

      Message getMessageAtRow(int row) {
       if (queueList == null)
        return null;
       return ((Message) queueList.get(row));
      }

                @Override
  public void tableChanged(TableModelEvent arg0) {
   // TODO Auto-generated method stub
   fireTableDataChanged();
  }

}

y obteniendo esta excepción.

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError  at javax.swing.table.AbstractTableModel.fireTableRowsInserted(Unknown Source)

¿Está mal?

¿Fue útil?

Solución

Según mi conocimiento, su JTable debería actualizarse automáticamente cuando ocurra un cambio en el TableModel . Consulte el tutorial de sun en trabajo con tablas y especialmente la sección sobre escuchar cambios de datos , esto puede ayudar. Dicho esto, tengo un par de comentarios:

  • Realmente no obtengo el método getValueAt (int row, int col) . ¿No debería obtener el mensaje de la fila y el atributo de la columna del mensaje?

  • Yo agregaría un addRow (...) y addRows (...) a la implementación de MsgTable de TableModel para actualizar el modelo interno y activar el evento apropiado.

  • No necesita implementar TableModelListener (no puedo ver ninguna llamada a addTableModelListener (...) de todos modos)

(EDITAR: El OP ha actualizado su pregunta con un nuevo código, por lo que estoy actualizando mi respuesta según corresponda a continuación).

Ha modificado la firma load (...) y el cuerpo para agregar una llamada a addTableModelListener (...) y creo que ambas modificaciones no son correcto.

Acerca de addTableModelListener (... ) , la documentación dice:

  

Agrega un oyente a la lista que recibe una notificación cada vez que se produce un cambio en el modelo de datos.

Y sobre los diversos métodos fireFooXxx (...) :

  

Notifica a todos los oyentes que [ocurrió un cambio]

Entonces, con la siguiente implementación de un TableModelListener :

@Override
public void tableChanged(TableModelEvent arg0) {
    // TODO Auto-generated method stub
    fireTableDataChanged();
} 

Terminarás haciendo infinitas llamadas recursivas (se notifica al oyente mediante un cambio y se activa un evento que le notificará nuevamente, etc.), por lo tanto, java.lang.StackOverflowError .

En realidad, sigo pensando que no necesita un TableModelListener (y la forma en que se está registrando no es la IMO correcta, consulte Escuchar cambios de datos en el tutorial de Sun). Por lo tanto, eliminaría los implementos TableModelListener y más bien implementaría el método load (...) como este:

void load(Enumeration e) {
    while(e.hasMoreElements()) {
        queueList.add(e.nextElement());
    }
    fireTableDataChanged();   
}

Otros consejos

Un par de puntos para agregar para consideración:

  • su método de load (Enumeration e) no necesita lanzar una JMSException , ya que solo está iterando sobre una Enumeration .
  • debe asegurarse de que su activación de eventos se realice dentro de la EDT. Esto podría ser tan simple como ajustar su llamada a load en un runnable y soltarla en SwingUtilities.invokeLater () :

    MsgTable mt = (MsgTable) queueTable.getModel();
    final Enumeration e = qb.getEnumeration();
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            mt.load(e);
        }
    });
    

una forma de mejorar el rendimiento sería llamar solo a fireTableDataChanged () al final del método load (), a diferencia de después de cargar cada línea.

eso debería ayudar.

es decir:

void load(Enumeration e) throws JMSException {
                 while(e.hasMoreElements()){
                         queueList.add(e.nextElement());
                         fireTableDataChanged();
                 }                      
        }

a

void load(Enumeration e) throws JMSException {
                 boolean dataAdded = false;
                 while(e.hasMoreElements()){
                         queueList.add(e.nextElement());
                         dataAdded = true;
                     }
                 fireTableDataChanged();

        }

Bueno, el diseño adecuado es crear un método addRow (...) que reciba una fila de datos y actualice el almacenamiento interno de su TableModel. Este método debería invocar el método fileTableRowsInserted (). Su método getValueAt () tampoco tiene sentido. Según su modelo, tiene 5 columnas de datos, sin embargo, nunca verifica la variable de columna para devolver el objeto de columna adecuado.

Eche un vistazo al código fuente de DefaultTableModel para ver cómo se pueden codificar los métodos insertRow () y getValueAt ().

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