2012-04-07 8 views
1

Ich habe eine einfache JFrame und eine JTable auf dem Rahmen. Benutzer können Daten in die Zeilen der Tabelle eingeben. Eine der Anforderungen besteht darin, dass die neuen Daten nach dem Schließen des Rahmens entweder gespeichert oder verworfen werden können. Ich dachte, dass der einfachste Weg, um dieses Verhalten zu erreichen, ist die folgende:Probleme mit dem Klonen des DataVector von DefaultTableModel

  1. Überschreibung der setVisible() Methode des Rahmens und klonen die DefaultTableModel ‚s Datenvektor.

  2. fügen Sie eine WindowListener in den Rahmen und reagieren für die WindowClosing Ereignisse. Auf diese Weise kann der Fenster-Listener entscheiden, ob das Modell auf das zuvor gespeicherte Modell zurückgesetzt werden soll.

Hier ist der relevante Code-Schnipsel:

@Override 
public void setVisible(boolean b) { 
    //save the original models only if setVisible invoked with true (do not save the model when hiding the frame) 
    if (b) { 
    Vector cloned = (Vector) userTableModel.getDataVector().clone(); 
    Vector headerNames = new Vector(); 
    originalModel = new CustomTableModel(cloned, headerNames); 
    } 
    super.setVisible(b); 
} 

Eigentlich etwas Unheimliches passiert. Nachdem ich den Datenvektor klonen, kann die Tabelle nicht wiedergegeben werden, und dies führt zu folgender Ausnahme:

 
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0 
    at java.util.Vector.elementAt(Vector.java:470) 
    at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:650) 
    at asc.model.CustomTableModel.getValueAt(CustomTableModel.java:74) 
    at javax.swing.JTable.getValueAt(JTable.java:2720) 

Die Tabelle auf den originalModel in keiner Weise in Verbindung ist. Es ist eine Überraschung für mich, weil das Klonen theoretisch das Modell der Tabelle nicht beeinflussen sollte. Die Absicht von originalModel ist es, einen Verweis auf die neu erstellte Kopie des Tabellenmodells zu halten. Nachdem ich die Erstellung des originalModel auskommentiert habe, hat alles gut funktioniert.

Eine weitere interessante Sache ist, wenn ich eine leeres String zum headerNames Vektor hinzugefügt, wirft die Tabelle Renderer fast die gleiche ArrayIndexOutOfBounds Ausnahme, aber mit dieser Endung:

 
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1 

In diesem Fall wird die erste Spalte der erste Reihe perfekt wiedergegeben.

Meine CustomTableModel ist von DefaultTableModel erweitert, und es verwendet keine spezielle Methode. Der Konstruktor übergibt einfach den Datenvektor und den Header-Vektor an die Oberklasse.

Ich hoffe, jemand könnte helfen, das Problem zu lösen. Vielen Dank im Voraus.

+2

für bessere Hilfe schneller bearbeiten Sie Ihre Frage mit [SSCCE] (http://sscce.org/) – mKorbel

Antwort

1

Ich glaube, dass Sie einen Fehler in Vector cloned haben, weil Sie kehrt versucht Ebene Vector aber JTable auf Vector<Vector> in Ihrem Fall basiert

1

Die Länge des headerNames Vektor die Anzahl der Spalten übereinstimmen muss Sie haben bekam. Es ist verwirrend, weil der Vector in ein Array von Header-Namen in der CustomTableModel-Klasse übersetzt wird, weshalb er als AIOOBE angezeigt wird.

So, ersten Durchlauf sieht es in der headerNames Vektor/Array für die erste Spalte (Spalte bei Index 0) und schlägt fehl, Senden der 0> = 0 Version des Fehlers. Sobald Sie eine Spaltennamen-Zeichenfolge hinzufügen (obwohl sie leer ist), rendert sie erfolgreich die gesamte erste Spalte und sucht dann nach der zweiten Spalte (Spalte bei Index 1). Es schlägt fehl, da Sie kein zweites Element in dem Vektor HeaderNames haben und die 1> = 1 Version des Fehlers gibt.

Stellen Sie sicher, dass der Vektor headerNames die richtige Anzahl von Werten hat (die der Anzahl der Spalten im Datenvektor entspricht) und Sie sollten gut gehen können.

Hinweis - die clone() - Methode erstellt eine SHOWOW-Kopie der Daten, sodass Änderungen an den Daten in den Zellen die ursprünglichen Objekte ändern. Dieser Artikel kann dabei helfen: http://javatechniques.com/blog/faster-deep-copies-of-java-objects/.

1

Eine Implementierung von AbstractTableModel gibt Ihnen direkte Kontrolle über Ihre Datenstruktur (en). Diese example veranschaulicht Map<String, String>, aber die Wahl ist willkürlich.