Aggiornamento da coda JMS a JTable [Ora ricevendo un'eccezione dopo le modifiche]

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

  •  06-07-2019
  •  | 
  •  

Domanda

Sto scrivendo il mio browser JMS e sono colpito dall'aggiornamento JTable di Messaggi dai server JMS. Ho provato AbstractTableModel TableModelListener per aggiornare Jtable quando i dati aggiunti in LinkedList. Questo logis sotto funziona, ma non si aggiorna in tempo reale, significa che I desidera visualizzare immediatamente ogni riga aggiunta a Jtable quando viene aggiunta da QueueBrowser a LinkedList.

Ho aggiornato il codice secondo i suggerimenti seguenti.

Sto facendo qualcosa di sbagliato? qualcuno può aiutarmi?

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

}

e ottenere questa eccezione.

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

È sbagliato?

È stato utile?

Soluzione

Per quanto ne so, il tuo JTable dovrebbe aggiornarsi automaticamente quando si verifica una modifica al TableModel . Dai un'occhiata al sun tutorial su lavorando con i tavoli e in particolare la sezione ascoltando le modifiche dei dati , questo può aiutare. Detto questo, ho un paio di osservazioni:

  • Non riesco proprio a ottenere il metodo getValueAt (int row, int col) . Non dovresti ottenere il messaggio row-th e l'attributo col-th del messaggio?

  • Aggiungerei un addRow (...) e addRows (...) alla MsgTable dell'implementazione di TableModel per aggiornare il modello interno e generare l'evento appropriato.

  • Non è necessario implementare TableModelListener (non vedo alcuna chiamata a addTableModelListener (...) ))

(EDIT: l'OP ha aggiornato la sua domanda con un nuovo codice, quindi sto aggiornando la mia risposta di conseguenza di seguito.)

Hai modificato la firma e il corpo di load (...) per aggiungere una chiamata a addTableModelListener (...) e penso che entrambe le modifiche non lo siano corretta.

Informazioni su addTableModelListener (... ) , la documentazione dice:

  

Aggiunge un listener all'elenco che viene notificato ogni volta che si verifica una modifica al modello di dati.

E sui vari metodi fireFooXxx (...) :

  

Notifica a tutti i listener che [si è verificato un cambiamento]

Quindi, con la seguente implementazione di un TableModelListener :

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

Finirai per effettuare infinite chiamate ricorsive (l'ascoltatore viene avvisato da una modifica e genererà un evento che lo notificherà di nuovo, ecc.), quindi java.lang.StackOverflowError .

In realtà, continuo a pensare che non hai bisogno di un TableModelListener (e il modo in cui lo stai registrando non è IMO corretto, vedi Ascolto di modifiche ai dati nel tutorial di Sun). Rimuoverei quindi implementa TableModelListener e implementerei piuttosto il metodo load (...) in questo modo:

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

Altri suggerimenti

Un paio di punti da considerare:

  • il tuo metodo load (Enumeration e) non ha bisogno di lanciare un JMSException , dato che stai solo iterando su un Enumeration .
  • dovresti assicurarti che il tuo lancio di eventi sia fatto all'interno dell'EDT. Questo potrebbe essere semplice come racchiudere la tua chiamata in carica in un runnable e rilasciarla in SwingUtilities.invokeLater () :

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

un modo per aumentare le prestazioni sarebbe quello di chiamare fireTableDataChanged () alla fine del metodo load (), al contrario di dopo che ogni riga è stata caricata.

che dovrebbe aiutare.

vale a dire:

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

        }

Bene, la progettazione corretta è quella di creare un metodo addRow (...) che riceve una riga di dati e aggiorna la memoria interna di TableModel. Questo metodo dovrebbe quindi invocare il metodo fileTableRowsInserted (). Anche il tuo metodo getValueAt () non ha senso. Secondo il tuo modello hai 5 colonne di dati, ma non controlli mai la variabile di colonna per restituire l'oggetto colonna corretto.

Dai un'occhiata al codice sorgente di DefaultTableModel per vedere come potrebbe essere codificato un metodo insertRow () e getValueAt ().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top