JMS-Warteschlange auf JTable Update [Jetzt bekommen Ausnahme nach Änderungen]
Frage
ich meinen eigenen JMS-Browser schreibe, und ich bin an der JTable Aktualisierung von Nachrichten von JMS-Server getroffen. Ich habe Das unten Logis funktioniert, aber es ist nicht die Aktualisierung in Echtzeit bedeutet würde Ich mag jede einzelne Zeile zu jtable hinzugefügt sofort, wenn angezeigt werden seine hinzugefügt von QueueBrowser zu LinkedList. AbstractTableModel
TableModelListener
versucht jtable refresh zu machen, wenn die Daten in LinkedList hinzugefügt.
Ich habe den Code gemäß den nachstehenden Empfehlungen aktualisiert.
Mache ich etwas falsch? kann mir jemand helfen?
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();
}
}
und diese Ausnahme zu bekommen.
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError at javax.swing.table.AbstractTableModel.fireTableRowsInserted(Unknown Source)
Ist es falsch?
Lösung
Meines Wissens sollte Ihr JTable
automatisch aktualisiert, wenn eine Änderung der TableModel
passiert. Schauen Sie sich die Sonne Tutorial auf Arbeit mit Tabellen und speziell der Abschnitt hören für Datenänderungen kann dabei helfen. Das heißt, ich habe ein paar Bemerkungen:
-
Ich habe nicht wirklich die
getValueAt(int row, int col)
Methode. Sollten Sie nicht die Zeile-ten Nachricht erhalten und das col-te Attribut der Nachricht? -
Ich würde eine
addRow(...)
undaddRows(...)
hinzufügen Implementierung von TablemodelMsgTable
des internen Modells zu aktualisieren und das entsprechende Ereignis aus. -
Sie brauchen nicht
TableModelListener
zu implementieren (ich keinen Anruf sehen sowiesoaddTableModelListener(...)
)
(EDIT:. Die OP wird aktualisiert seine Frage mit neuem Code, damit ich entsprechend unter meiner Antwort bin Aktualisierung)
Sie haben die load(...)
Unterschrift und Körper modifiziert, um einen Anruf hinzufügen, um addTableModelListener(...)
und ich denke, dass beide Modifikationen, die nicht korrekt sind.
Über die addTableModelListener (... ), die Dokumentation sagt:
Fügt einen Listener zu der Liste, die jedes Mal, wenn eine Änderung auftritt, auf das Datenmodell benachrichtigt wird.
Und über die verschiedenen fireFooXxx(...)
Methoden:
Benachrichtigt alle Zuhörer, dass [eine veränderte aufgetreten]
So mit der folgenden Implementierung eines TableModelListener
:
@Override
public void tableChanged(TableModelEvent arg0) {
// TODO Auto-generated method stub
fireTableDataChanged();
}
Sie werden unendlich rekursive Anrufe am Ende machen (der Hörer durch eine Änderung informiert wird und ein Ereignis ausgelöst, die ihn wieder usw. mitteilen werden), damit die java.lang.StackOverflowError .
Eigentlich, denke ich immer noch, dass Sie brauchen keine TableModelListener
(und so, wie Sie es sind Registrierung nicht IMO korrekt ist, finden Sie unter für Daten Zuhören Änderungen in den Sun-Tutorial). Ich würde so die implements TableModelListener
entfernen und lieber die load(...)
Methode wie folgt implementieren:
void load(Enumeration e) {
while(e.hasMoreElements()) {
queueList.add(e.nextElement());
}
fireTableDataChanged();
}
Andere Tipps
Ein paar Punkte zur Prüfung hinzuzufügen:
- Ihre
load(Enumeration e)
Methode benötigt keineJMSException
zu werfen, wie Sie gerade über einenEnumeration
iterieren. -
Sie sollten sicherstellen, dass Ihre Abfeuern von Ereignissen innerhalb des EDT erfolgt. Dies könnte so einfach sein wie Ihren Anruf Einwickeln in einem runnable
load
und inSwingUtilities.invokeLater()
fallen:MsgTable mt = (MsgTable) queueTable.getModel(); final Enumeration e = qb.getEnumeration(); SwingUtilities.invokeLater(new Runnable() { public void run() { mt.load(e); } });
Ein Weg, um die Leistung bis zu nur nennen fireTableDataChanged wäre () am Ende der Last () Methode, im Gegensatz zu nach jeder Zeile geladen wird.
das sollte helfen.
ie:
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();
}
Nun, das ist die richtige Gestaltung eines addRow (...) Methode zu erstellen, die eine Reihe von Daten empfängt und aktualisiert die interne Speicherung Ihrer Tablemodel. Diese Methode sollte dann die fileTableRowsInserted () -Methode aufrufen. Ihre getValueAt () -Methode macht auch keinen Sinn. Nach Ihrem Modell haben Sie 5 Spalten von Daten, aber Sie überprüfen nie die Spaltenvariable die richtige Spalte Objekt zurück.
Werfen Sie einen Blick auf den Quellcode des DefaultTableModel zu sehen, wie ein insertRow () und getValueAt () -Methode können codiert werden.