Mise à jour de la file d'attente JMS vers JTable [Obtention d'une exception après chaque modification]

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

  •  06-07-2019
  •  | 
  •  

Question

J'écris mon propre navigateur JMS et je suis frappé par la mise à jour JTable des messages à partir des serveurs JMS. J'ai essayé AbstractTableModel TableModelListener pour actualiser Jtable lorsque les données ajoutées à LinkedList. Ce logis ci-dessous fonctionne, mais ne met pas à jour en temps réel, signifie I souhaite afficher chaque ligne ajoutée à Jtable immédiatement après son ajout de QueueBrowser à LinkedList.

J'ai mis à jour le code conformément aux suggestions ci-dessous.

Est-ce que je fais quelque chose de mal? quelqu'un peut-il m'aider?

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

}

et obtenir cette exception.

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

Est-ce que c'est faux?

Était-ce utile?

La solution

À ma connaissance, votre JTable devrait se mettre à jour automatiquement lorsqu’une modification du TableModel a lieu. Consultez le didacticiel Sun sur utiliser des tableaux et spécialement la section sur écouter les modifications de données , cela peut aider. Cela dit, j'ai quelques remarques à faire:

  • Je ne comprends pas vraiment la méthode getValueAt (int row, int col) . Ne devriez-vous pas obtenir le message de la ligne-ème et l'attribut de la colonne de la message?

  • Je voudrais ajouter un addRow (...) et addRows (...) à MsgTable implémentation de TableModel mettre à jour le modèle interne et déclencher l'événement approprié.

  • Vous n'avez pas besoin d'implémenter TableModelListener (je ne vois aucun appel à addTableModelListener (...) de toute façon)

(EDIT: le PO a mis à jour sa question avec le nouveau code, donc je mets à jour ma réponse en conséquence ci-dessous.)

Vous avez modifié la signature et le corps de load (...) pour ajouter un appel à addTableModelListener (...) et je pense que les deux modifications ne sont pas correct.

À propos de la addTableModelListener (... ) , la documentation indique:

  

Ajoute un écouteur à la liste, lequel est averti à chaque modification du modèle de données.

Et à propos des différentes méthodes fireFooXxx (...) :

  

Notifie tous les écouteurs que [un changement a eu lieu]

Donc, avec l'implémentation suivante d'un TableModelListener :

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

Vous finirez par faire des appels récursifs infinis (l'auditeur est averti par un changement et déclenche un événement qui le notifiera à nouveau, etc.), d'où le java.lang.StackOverflowError .

En fait, je pense toujours que vous n’avez pas besoin d’un TableModelListener (et que la façon dont vous vous enregistrez n’est pas une bonne OMI, voir Écoute des modifications de données dans le didacticiel Sun). Je supprimerais donc le implémentant TableModelListener et mettrais plutôt en œuvre la méthode load (...) comme ceci:

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

Autres conseils

Quelques points à ajouter pour examen:

  • votre méthode load (énumération e) n'a pas besoin de générer une exception JMS , car vous ne faites qu'itérer sur une énumération .
  • vous devez vous assurer que les événements sont déclenchés dans l’EDT. Cela pourrait être aussi simple que d'encapsuler votre appel à load dans un exécutable et de le déposer dans SwingUtilities.invokeLater () :

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

Pour augmenter les performances, il suffit d'appeler fireTableDataChanged () à la fin de la méthode load (), et non après le chargement de chaque ligne.

cela devrait aider.

c'est-à-dire:

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

à

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

        }

La conception appropriée consiste à créer une méthode addRow (...) qui reçoit une ligne de données et met à jour le stockage interne de votre TableModel. Cette méthode doit ensuite invoquer la méthode fileTableRowsInserted (). Votre méthode getValueAt () n’a également aucun sens. Selon votre modèle, vous avez 5 colonnes de données, mais vous ne cochez jamais la variable de colonne pour renvoyer le bon objet de colonne.

Examinez le code source de DefaultTableModel pour voir comment une méthode insertRow () et getValueAt () peut être codée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top