Esther: Tabelle neu laden

Hi

Ich initialisere eine Tabelle mit bestimmten Werten im Stil von:

JTable jtable = new JTable(Object[][] rowData, Object[] columnNames)

Zu einem späteren Zeitpunkt möchte ich dieselbe Tabelle aber mit dem inzwischen geänderten Object[][] laden.

Wie kann ich das am einfachsten realisieren?

Danke für eure Hilfe

Gruss E.

  1. Hallo,

    JTable jtable = new JTable(Object[][] rowData, Object[] columnNames)

    Zu einem späteren Zeitpunkt möchte ich dieselbe Tabelle aber mit dem inzwischen geänderten Object[][] laden.

    Die Daten der JTable befinden sich in einem Model. Konkret handelt es
    sich dabei um eine Klasse, die javax.swing.table.TableModel implementiert.
    JTable verwendet von Haus aus javax.swing.table.DefaultTableModel.

    Du hast 2 Möglichkeiten:

    1. Du weist der JTable eine neue TabelModel-Instanz zu. Hierfür mußt
       du die Methode JTable.setModel(Model) verwenden.
       Lege beispielweise ein neues DefaultTableModel-Objekt an. Es steht
       ein Konstruktor zur Verfügung, der die Zelleninhalte und die
       Spaltennamen aufnimmt. (Genau wie der Konstruktor von JTable.)
       Übergib dieses Objekt der setModel-Methode.

    2. Da du (jetzt) weißt, daß JTable eine Instanz von DefaultTableModel
       als Model verwendet, kannst du dir mit der Methode JTable.getModel()
       dieses Objekt geben lassen, es nach DefaultTableModel casten und
       dann die Methode DefaultTableModel.setDataVector(Object[][], Object[])
       dazu verwenden, um die Daten im Model festzulegen.
       Wenn du sicher gehen willst, daß wirklich ein DefaultTableModel-
       Objekt als Model verwendet wird, kannst du das Model auch nach dem
       erzeugen der JTable von Hand setzen. Etwa so (ungetestet!):
           DefaultTableModel dtm   = new DefaultTableModel(data, columns);
           JTable            table = new JTable(dtm);
       So könntest du dir auch gleich das Model (dtm) in einer Instanz-
       variable speichern und müßtest dann nicht immer JTable.getModel()
       aufrufen um an das Model zu kommen.

    Falls dir die Geschichte mit dem Model spanisch vorkommt, würde ich
    dir ein Java-Buch deiner Wahl (am besten http://www.javabuch.de oder
    http://www.galileocomputing.de/openbook/javainsel3/), sowie die Tutorials
    von Sun zum Thema (Links findest du in der API-Doku zu JTable und
    TableModel) und den Java Almanach (http://javaalmanac.com/egs/?) empfehlen.

    Gruß
    Slyh

    1. Hallo Slyh

      Danke für deine ausführliche Antwort. Ich bin mir jedoch nicht sicher ob du mich richtig verstanden hast. Das Array, mit welchem ich ursprünglich die Tabelle fülle, wird später geändert (Aber völlig unabhängig von der Tabelle) Nun sollte die Tabelle neu geladen werden, das Array ist immernoch dasselbe...

      G. E

      1. Hallo,

        Danke für deine ausführliche Antwort. Ich bin mir jedoch nicht sicher ob du mich richtig verstanden hast. Das Array, mit welchem ich ursprünglich die Tabelle fülle, wird später geändert (Aber völlig unabhängig von der Tabelle) Nun sollte die Tabelle neu geladen werden, das Array ist immernoch dasselbe...

        Was denn nun? Wird das Array geändert oder wird es nicht geändert? :)
        Und was meinst du damit, daß es geändert wird?

        Ändern sich nur die Objekte selbst, die sich "im Array befinden"?
        (Eigentlich sind es ja nur Referenzen auf die konkreten Objekte.
        Ich meine die Objekte.) Oder ersetzt du auch einzelne Array-Elemente?

        Im ersten Fall dürfte die Änderung direkt von der JTable übernommen.
        (Mach zur Sicherheit mal ein Repaint.) Ansonsten mußt du wie von mir
        beschrieben das TableModel updaten/neu setzen.

        Falls du dir nicht sicher bist, dann beschreib dich mal möglichst genau
        was für Daten du hast, was du am Array änderst und welches Ergebnis
        du erwartest.

        Gruß
        Slyh

        1. Hallo Slyh

          OK, ich versuchs noch einmal. Es sind Bücherdaten, welche als Objekte aus einem Textfile eingelesen und in einen Vector geschrieben werden. Anschliessend wird der Vector in ein Array umgewandelt, sodass er in der Tabelle angezeigt werden kann (es gibt zwar eine Methode um Tabellen mit Vectoren zu laden, habe ich aber nicht hingekriegt:

          public void initTable() {

          String columnNames[] = {"ID", "Title", "Author", "Date"};
           String rowData[][] = new String[bManager.vBooks.indexOf(bManager.vBooks.lastElement())+1][4];

          for(int i=0; i<=bManager.vBooks.indexOf(bManager.vBooks.lastElement());i++) {
                  rowData[i][0] = String.valueOf((((Book)bManager.vBooks.elementAt(i)).bookID));
                  rowData[i][1] = (((Book)bManager.vBooks.elementAt(i)).author);
                  rowData[i][2] = (((Book)bManager.vBooks.elementAt(i)).title);
                  rowData[i][3] = (((Book)bManager.vBooks.elementAt(i)).year);
           }

          table = new JTable(rowData, columnNames);
              table.setEnabled(false);

          JScrollPane sp = new JScrollPane(table);
              sp.setBounds(20,150,400,150);
              cp.add(sp);

          }

          Zu einem späteren Zeitpunkt fügt der Benutzer ein neues Buch hinzu. Das Buch wird diesem Vector angefügt. Jetzt muss natürlich das Buch auch in der Tabelle angezeigt, dh. die Tabelle neu geladen werden.

          Ich hoffe es ist verständlich geworden.

          Danke.

          Gruss Esther

          1. Guude!

            Hallo Slyh

            Ich fühle mich jetzt einfach auch mal angesprochen ;-)

            es gibt zwar eine Methode um Tabellen mit Vectoren zu laden, habe ich aber nicht hingekriegt:

            Das hat mir anfangs auch Probleme bereitet, ist aber gar nicht so schwer und dabei noch wesentlich flexibler: Wenn Du zwei Vektoren hast, z.B. "vColNames" mit den Spaltennamen und "vData" mit den Tabellendaten (jedes Element des Datenvektors steht für eine Zeile und muss entweder einen weiteren Vektor oder ein Array für die jeweiligen Spalten der Zeile enthalten), weist Du die einem Tabellenmodell zu und registrierst dieses:

            DefaultTableModel dtm = new DefaultTableModel(vData, vColNames);
            JTable table = new JTable(dtm);

            Das Buch wird diesem Vector angefügt. Jetzt muss natürlich das Buch auch in der Tabelle angezeigt, dh. die Tabelle neu geladen werden.

            Füge das neue Buch doch direkt in die Tabelle ein:

            Vector neueZeile = new Vector(4);
            neueZeile.add(neuesBuch.bookID);
            neueZeile.add(neuesBuch.author);
            neueZeile.add(neuesBuch.title);
            neueZeile.add(neuesBuch.year);
            ((DefaultTableModel)table.getModel()).addRow(neueZeile);
            table.repaint();

            Wie Slyh schon sagte, enthält das TableModel alle Tabelleninhalte. Wenn Du also mit den Daten einer Tabelle arbeiten möchtest, dann greife auf sie direkt über das Tabellenmodell zu. Gerade das DefaultTableModel bietet dazu eine ganze Reihe nützlicher Methoden (siehe http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/table/DefaultTableModel.html).

            LG ausm Hesseland
            Lemmy

            --
            Wer seiner Frau gegenüber stets beteuert, dass DAS tatsächlich 30cm sind, darf sich nicht wundern, wenn sie nicht richtig einparken kann...
            1. Hallo Lemmy und Slyh

              Ihr habt mich überzeugt, ich habe auf DefaultTableModel und Vectoren umgestellt. Der Code sieht so aus:

              public void initTable() {

              Vector vData = new Vector();
              Vector vColumnNames = new Vector(4);

              vColumnNames.add("ID");
              vColumnNames.add("Title");
              vColumnNames.add("Author");
              vColumnNames.add("Date");

              for(int i=0; i<=bManager.vBooks.indexOf(bManager.vBooks.lastElement());i++) {
                  String rowData[] = new String[4];

              rowData[0] = String.valueOf((((Book)bManager.vBooks.elementAt(i)).bookID));
                  rowData[1] = (((Book)bManager.vBooks.elementAt(i)).author);
                  rowData[2] = (((Book)bManager.vBooks.elementAt(i)).title);
                  rowData[3] = (((Book)bManager.vBooks.elementAt(i)).year);

              vData.add(rowData);
              }

              DefaultTableModel dtm = new DefaultTableModel(vData, vColumnNames);
                  JTable table = new JTable(dtm);

              JScrollPane sp = new JScrollPane(table);
                  sp.setBounds(20,150,400,150);
                  cp.add(sp);
              }

              und jetzt hab ich den Schlammasel...:

              Exception in thread "main" java.lang.ClassCastException
                      at javax.swing.table.DefaultTableModel.justifyRows(DefaultTableModel.jav
              a:238)
                      at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.j
              ava:194)
                      at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:131
              )
                      at BookFrame.initTable(BookFrame.java:147)
                      at BookFrame.<init>(BookFrame.java:41)
                      at BookFrame.main(BookFrame.java:254)

              Was nun? Woran liegt das wohl?

              Gruss und Danke für eure Hilfe
              Esther

              1. Hallo Esther!

                String rowData[] = new String[4];

                Kann es sein, dass dies hier oben Deine Zeile 147 ist? Du hast die eckigen Klammern falsch gesetzt: "String[] rowData = new String[4];" sollte es heißen.

                Ansonsten kann ich so auf die Schnelle nichts Falsches entdecken.

                LG ausm Hesseland
                Lemmy

                --
                Wer seiner Frau gegenüber stets beteuert, dass DAS tatsächlich 30cm sind, darf sich nicht wundern, wenn sie nicht richtig einparken kann...
                1. Hallo Esther!

                  String rowData[] = new String[4];

                  Kann es sein, dass dies hier oben Deine Zeile 147 ist? Du hast die eckigen Klammern falsch gesetzt: "String[] rowData = new String[4];" sollte es heißen.

                  »»

                  das ist doch egal, beides ist gleich richtig und funktioniert gleich. Daran liegt es nicht...

                  Dominik

                  1. Guude!

                    das ist doch egal, beides ist gleich richtig und funktioniert gleich. Daran liegt es nicht...

                    Tatsächlich? Zumindest hab ich die Schreibweise so noch nicht gesehen. Dass es daran nicht liegen kann, ist schon klar, denn 1. hätte es der Compiler angemeckert und 2. erzeugt es keine ClassCastException. In Zeile 238 der Methode justifyRows() des DefaultTableModels heißt es:

                    ((Vector)dataVector.elementAt(i)).setSize(getColumnCount());

                    Zeilen müssen also einen Vector anstelle eines Array enthalten, sonst kommt es hier zu der ClassCastException. Fehler meinerseits - sorry. Aber eigentlich doof von mir, nochmal zu antworten, denn Esther hatte es experimentell ja schon ermittelt und hinbekommen. Die Gans im Bauch drückt halt auf's Hirn... ;-)

                    LG ausm Hesseland
                    Lemmy

                    --
                    Wer seiner Frau gegenüber stets beteuert, dass DAS tatsächlich 30cm sind, darf sich nicht wundern, wenn sie nicht richtig einparken kann...
            2. Hallo Lemmy

              und muss entweder einen weiteren Vektor oder ein Array für die jeweiligen Spalten der Zeile enthalten)...

              Also mit einem Array klappts nicht, mit einem Vector schon:-)

              Gruss Esther