JTable - wie ändere ich den Inhalt dynamisch

jorgeHX

Erfahrenes Mitglied
Hallo,
ich habe folgendes Problem:


Ich erstelle in einer Klasse ein Tablemodel und weise es einem JTable zu.
Der Inhalt meines Tablemodels soll nun dynamisch verändert werden.
Jedesmal wenn ich den neuen modifizierten Inhalt aus meiner Datenbank lade, wird dieser neue Inhalt aber nicht angezeigt.

Hier die relevanten Ausschnitte aus meinem Quelltext:
Code:
// wird nach Klick auf die TabPane aufgerufen
class Aufstellung extends JPanel{
    JTable aufstellung_tb = new JTable();
    private AufstellungTableModel tablemodel;
 
     public Aufstellung(){
         getTable();
    }


private void getTable() throws Exception{

    String stm = "SELECT PersonID FROM nimmtTeilSpiel WHERE SpieltagID=" +
        spieltagDAO.getKey();

    ResultSet rs = Frame.db.query(stm);

  //count the results
    int rows = 0;

    while (rs.next()) {
      rows++;
    }


    //create a properly sized array
    PersonDAO[] retval = new PersonDAO[rows];

    //query again and fill the array
    rs = Frame.db.query(stm);

    int i = 0;
    while (rs.next()) {
      retval[i] = new PersonDAO(rs.getLong(1));
      i++;
    }

    tablemodel = new AufstellungTableModel(retval);
    aufstellung_tb.setModel(tablemodel);


    //System.out.println(retval.length);
    rs.close();
    Frame.db.stm.close();
  }
}

public class AufstellungTableModel extends AbstractTableModel {

  PersonDAO[] aufstellung;

  public AufstellungTableModel(PersonDAO[] aufstellung) {
    this.aufstellung = aufstellung;
  }

  // die Menge der Zeilen ergibt sich aus der Summe aller drei Übungsteilen
  public int getRowCount() {
    return aufstellung.length;
  }

  // es gibt immer 3 Spalten in dieser Tabelle
  public int getColumnCount() {
    return 1;
  }

  public String getColumnName(int columnIndex) {
    switch (columnIndex) {
      case 0:
        return "Spielername";
      default:
        return "Das dürfte hier jetzt nicht stehen!";
    }
  }

  public Object getValueAt(int rowIndex, int columnIndex) throws Exception{
    //Wenn die Übung eine Pause ist setzte eine Pause
    System.out.println(aufstellung[rowIndex].getLastName()+", "+aufstellung[rowIndex].getFirstName());

      return aufstellung[rowIndex].getLastName()+", "+aufstellung[rowIndex].getFirstName();

    }
}


Das Problem erscheint mir so, dass der alte Inhalt von meinem tablemodel nicht richtig aktualisiert wird. Vielmehr verdeckt der alte Inhalt den neuen.....

Ich hoffe jemand hat eine Idee und Lösung,
Jorge
 
Tach,
Du musst nur an der Stelle, wo Du das Array aufstellung[] im TableModel änderst, fireTableDataChanged() auf dem TableModel aufrufen.
 
Hallo,
meinst du so?


....

tablemodel = new AufstellungTableModel(retval);
tablemodel.fireTableDataChanged();
aufstellung_tb.setModel(tablemodel);

....


Das funktioniert leider nicht
:(
 
Original geschrieben von jorgeHX
Hallo,
meinst du so?

....
tablemodel = new AufstellungTableModel(retval);
tablemodel.fireTableDataChanged();
aufstellung_tb.setModel(tablemodel);
....

Das funktioniert leider nicht
:(

Nicht ganz.
Du begehst einen Kardinalfehler. Du erzeugst für jedes ResultSet ein eigenes TableModel. Das sollte so nicht sein. Weise lediglich initial der JTable einmal das TableModel zu und implementiere eine Methode setData(PersonDAO[] aufstellung) in Deinem TableModel. Darin weist Du lediglich das übergebene Array der lokalen Variable aufstellung zu - natürlich incl. zugehöriger Sicherheitsabfragen. Dann in der getTable()-Methode die Zeilen

Code:
tablemodel = new AufstellungTableModel(retval);
aufstellung_tb.setModel(tablemodel);

ändern in
Code:
tablemodel.setData(retval);
tablemodel.fireTableDataChanged();

Der Konstruktor des TableModels benötigt dann auch keinen Übergabeparameter.
 
Hier der geänderte relevante Ausschnitt aus meinem Quelltext:
Code:
// wird nach Klick auf die TabPane aufgerufen
class Aufstellung extends JPanel{
JTable aufstellung_tb = new JTable();
private AufstellungTableModel tablemodel = new AufstellungTableModel();

public Aufstellung(){
getTable();
aufstellung_tb.setModel(tablemodel);

}


private void getTable() throws Exception{

String stm = "SELECT PersonID FROM nimmtTeilSpiel WHERE SpieltagID=" +
spieltagDAO.getKey();

ResultSet rs = Frame.db.query(stm);

//count the results
int rows = 0;

while (rs.next()) {
rows++;
}


//create a properly sized array
PersonDAO[] retval = new PersonDAO[rows];

//query again and fill the array
rs = Frame.db.query(stm);

int i = 0;
while (rs.next()) {
retval[i] = new PersonDAO(rs.getLong(1));
i++;
}

tablemodel.setData(retval);
tablemodel.fireTableDataChanged();

//System.out.println(retval.length);
rs.close();
Frame.db.stm.close();
}
}


public class AufstellungTableModel extends AbstractTableModel {

  PersonDAO[] aufstellung;

  public AufstellungTableModel() {

  }

  public void setData (PersonDAO[] aufstellung)throws Exception{
      this.aufstellung = aufstellung;
    }

  // die Menge der Zeilen ergibt sich aus der Summe aller drei Übungsteilen
  public int getRowCount() {
    return aufstellung.length;
  }

  // es gibt immer 3 Spalten in dieser Tabelle
  public int getColumnCount() {
    return 1;
  }

  public String getColumnName(int columnIndex) {
    switch (columnIndex) {
      case 0:
        return "Spielername";
      default:
        return "Das dürfte hier jetzt nicht stehen!";
    }
  }

  public Object getValueAt(int rowIndex, int columnIndex) throws Exception{
    //Wenn die Übung eine Pause ist setzte eine Pause
    System.out.println(aufstellung[rowIndex].getLastName()+", "+aufstellung[rowIndex].getFirstName());

      return aufstellung[rowIndex].getLastName()+", "+aufstellung[rowIndex].getFirstName();

    }

}

Es will sich einfach nicht aktualisieren und vor allem ist es so, dass die Methode getValueAt nach jedem hin und her springen in der TabPane um aufstellung.length mal mehr aufgerufen wird. Das habe ich gemerkt als ich einaml System.out.println aufgerufen habe. Anfangs gibt er die veränderte Liste aus und dann wieder den alten Zustand.
Dabei will ich doch einfach nur den neuen aktuellen Inhalt ausgeben. Das kann doch nicht so kompliziert sein, oder?
Tausend Dank schon jetzt
 
>Hier der geänderte relevante Ausschnitt aus meinem Quelltext:

>public Aufstellung(){
>getTable();
>aufstellung_tb.setModel(tablemodel);
>}

Du solltest die beiden Zeilen vertauschen.
Und auch mal die Methode getTable umbenennen in setTableData, setTableValues oder so. Wenn man getTable liest, erwartet man üblicherweise die Rückgabe einer JTable. In Deinem Fall würde eine getTable Implementierung mich zumindest folgendes erwarten lassen:

Code:
private JTable getTable()
{
 return aufstellung_tb;
}

>Es will sich einfach nicht aktualisieren und vor allem ist es so, dass die Methode getValueAt nach jedem hin und her springen in der TabPane um aufstellung.length mal mehr aufgerufen wird. Das habe ich gemerkt als ich einaml System.out.println aufgerufen habe. Anfangs gibt er die veränderte Liste aus und dann wieder den alten Zustand.

Dann behaupte ich mal, dass der Fehler nicht in diesen Codefragmenten liegt. Rufst Du eigentlich nur im Konstruktor von Aufstellung die getTable-Methode auf? Oder noch an anderer Stelle?
 
Morgen,
also die Zeilen habe ich vertauscht, aber dennoch verändert sich nichts.
Die Methode "setTable" rufe ich nur im Konstruktor auf. Woanders macht sie ja keinen Sinn in meinen Augen.

Den Datensatz, den ich in der JTable jedesmal darstellen will, ändere ich zuvor in "tab==1".
Anschließend klicke ich auf meine "tab==2" und rufe demzufolge den Konstruktor Aufstellung() auf. Dieser sollte dann durch die Methode "setTable" dafür sorgen, dass der veränderte Inhalt in der JTable angezeigt wird. Tut er aber nicht.

Wie gesagt, es erscheint jedesmal so, als wenn das Tablemodel den neuen Inhalt mit den alten Inhalten überschreibt.
Ich habe ja durch den Aufruf von System.out.println gesehen, dass folgendes passiert....

Klick auf Tab==2 und anschauen der geladenen Datensätze. Das Programm gibt folgendes aus:
Mr. X
Mr. XY
Mr. Z

Dann Klick auf Tab==1 und hinzufügen von Mr. Q, dann klick auf Tab==2 und das Programm gibt folgendes aus:
Mr. X
Mr.XY
Mr.Z
Mr.Q
Mr.X
Mr.XY
Mr.Z

Füge ich noch einen Namen hinzu, verlängert sich die Ausgabe dementsprechend. In der JTable ändert sich aber wieder nichts. Hilft das vielleicht weiter?
 
Mir zumindest nicht, da ich die Programmlogik und die Umsetzung nicht so ganz nachvollziehen kann.

Übrigens ist eine JTabbedPane nicht unbedingt dazu gedacht, nach jedem Tab-Wechsel immer wieder ein neues Panel zu erstellen...
 
Aber wie soll ich es sonst realisieren?
Ich rufe in der Klasse "MeineTabPane" die Methode

public void stateChanged( ChangeEvent ce){
tp.setBounds(new Rectangle(0, 0, 630, 570));

int tab = tp.getSelectedIndex();
....
else if (tab == 2){
try {
Aufstellung aufstellung = new Aufstellung(spieltagDAO);
aufstellung_pl.add(aufstellung, BorderLayout.CENTER);
tp.repaint();

tp.setBounds(new Rectangle(0, 0, 630, 570));

}
....
}

auf und demzufolge den Konstruktor von Aufstellung();
Alles andere bleibt wie gehabt. Sonst kann ich den geänderten Inhalt der TabPane doch nicht neu darstellen, oder?
 
Zurück