JTable dynamisch füllen.

Phil_adelphia

Grünschnabel
Hallo!

Ich habe eine Gui, die bei Klick auf einen Button verschiedene Berechnungen durchführt. Danach sollen die Ergebnisse in der Gui angezeigt werden.
Als Darstellungsart habe ich mir eine JTable rausgesucht,da ich die Ergebnisse gruppieren muss.
Die JTable erstelle ich im Kopf der Klasse mit " public JTable table; " und rufe sie dann im Action Listener mit "

repaint();
table = new JTable(main.getAdmin().ram,main.getAdmin().columnames);

table.setBounds(30,250,500,250);
panel.add(table);
repaint();

" auf.
"ram" ist mein 2 dimensionales String Array und Columnames mein eindimensionales Stringarray für die Spaltenbezeichnung.
in "ram" sind die Werte enthalten die ich dynamisch ausgeben möchte.

Leider bekomme ich immer folgende Fehlermeldung:
"Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.JTable$1.getColumnName(Unknown Source)
at javax.swing.JTable.addColumn(Unknown Source)
at javax.swing.JTable.createDefaultColumnsFromModel(Unknown Source)
at javax.swing.JTable.tableChanged(Unknown Source)
at javax.swing.JTable.setModel(Unknown Source)
at javax.swing.JTable.<init>(Unknown Source)
at javax.swing.JTable.<init>(Unknown Source)
at javax.swing.JTable.<init>(Unknown Source)
at gui.actionPerformed(gui.java:215)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)".

Eigentlich dachte ich,dass JTable ein 2 dimensionales Stringarray verlangt.
Initialisiere ich allerdings die JTable mit table = new JTable(2,3); oder anderen Werte wird die Tabelle perfekt angezeigt.Nur leider ohne Inhalt.
Woran kann die Fehlermeldung liegen? Verlangt JTable vielleicht doch kein Stringarray? Oder gibt es sonst etwas auf das man achten muss?
Vor allem, da ich die Übergabe der Werte getestet habe und die Variablen initialisiert und gefüllt sind.

Hoffentlich kann mir jemand bei diesem Problem helfen.
Ich verzweifle sonst noch ;-)

Dank und Grüsse
Philipp
 
Hallo,

wie es aussieht, stimmt was mit den Daten nicht, die Du aus dem main.getAdmin() holst. Entweder ist der Daten-Vector (noch) null, oder die Anzahl von Spalten im Daten-Vector und im columnames-Array schtimmt nicht überein. Am besten, Du gibst in der actionPerformed() die Daten aus, bevor Du sie in die Tabelle setzt.

Abgesehen davon, würde ich Dir sowieso raten, das Updaten von Daten in der Tabelle, etwas anders zu gestalten, denn, wenn Du bei jeder Datenänderung die JTable neu erzeugst, sie dann in das panel setzt und davor und danach repaint() aufrufst, wird Deine GUI sehr langsamm, und langsame GUIs nerven den Benutzer. :)

Also erstens, wenn die Spaltennamen konstant bleiben (was oft der Fall ist), macht es Sinn, sie einmal zu definieren; zweitens, erzeuge die Tabelle im Konstruktor Deiner GUI-Klasse mit einem leeren Daten-Array und setze sie in eine ScrollPane; drittens, überprüfe in Deiner actionPerformed() Methode, ob die Daten zu verfügung stehen, es macht keinen Sinn null-Werte in die Tabelle zu setzen; viertens, setze die neuen Daten in das TableModel und schicke das TableDataChanged-Event, um den Table-View upzudaten (vielleicht wird es nicht nötig sein, wirst Du sehen). Demnach könnte Dein Code etwa so aussehen:
Code:
    ...
    private final String[] columnNames = {"Column 1", "Column 2", "Column 3"};
    private JTable table;
    ...
    public MyGUIClass() {
        table = new JTable(new Object[0][3], columnNames);
        panel.add(new JScrollPane(table));
    }
    ...
    public void actionPerformed(ActionEvent e) {
        // hier nur die Daten in dem TableModel updaten
        final Object[][] data = main.getAdmin().ram;
        if ((data == null) || (data.length == 0)) {
            // wenn die Daten noch nicht verfügbar sind
            // macht das Update keinen Sinn
            return;
        }
        final DefaultTableModel model = (DefaultTableModel) table.getModel();
        model.setDataVector(data, columnNames);

        // kann sein, dass das hier überflüssig ist, musst Du testen ;)
        model.fireTableDataChanged();
    }
    ...

Gruß
Vincent
 
Hi Vincentius.

Danke für deine detailierte Antwort.
Ich werde die Änderungen mal vornehmen und mich durchkauen ;-)

Vielen Dank!
Grüsse Philipp
 
Moin,
vor allem nimm Dir mal das (Default)TableModel zur Brust, sonst wird das nie was mit einer sauberen Tabellenimplementierung.
 
Hi Leute,

ich habe es geschafft meine Tabelle mit den Sachen zu füllen, die rein sollen.
So jetzt möchte ich aber ne neue Abfrage machen und nur die neuen Daten in der Tabelle anzeigen.
Die Abfrage funktioniert, aber die Daten werden nicht dargestellt.
Daraufhin habe ich mir das Codebeispiel vorgenommen und diesen "Refresh" versucht.
Der erste lauf klappt wie bisher fehlerfrei (da brauche ich das DefaultTableModel auch nicht), aber wenn ich dann die neue Abfrage anzeigen lassen will kracht es an folgender Stelle:

final DefaultTableModel model = (DefaultTableModel)tabelle.getModel();


mit folgender Fehlermeldung:

Exception occurred during event dispatching:
java.lang.ClassCastException: javax.swing.JTable$2
at EingabeFenster$ButtonListener.actionPerformed(EingabeFenster.java:74)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1450)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1504)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:384)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:256)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:220)
at java.awt.Component.processMouseEvent(Component.java:3771)
at java.awt.Component.processEvent(Component.java:3600)
at java.awt.Container.processEvent(Container.java:1173)
at java.awt.Component.dispatchEventImpl(Component.java:2649)
at java.awt.Container.dispatchEventImpl(Container.java:1222)
at java.awt.Component.dispatchEvent(Component.java:2553)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:2465)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2230)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2139)
at java.awt.Container.dispatchEventImpl(Container.java:1209)
at java.awt.Window.dispatchEventImpl(Window.java:923)
at java.awt.Component.dispatchEvent(Component.java:2553)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:401)
at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:109)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:99)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)


Woran könnte das liegen?
Achja und wie bekomme ich die Scrollbalken angezeigt

Vielen Dank für eure Hilfe.

mfg,
Profiler
 
Profiler83 hat gesagt.:
Hi Leute,

ich habe es geschafft meine Tabelle mit den Sachen zu füllen, die rein sollen.
So jetzt möchte ich aber ne neue Abfrage machen und nur die neuen Daten in der Tabelle anzeigen.
Die Abfrage funktioniert, aber die Daten werden nicht dargestellt.
Daraufhin habe ich mir das Codebeispiel vorgenommen und diesen "Refresh" versucht.
Der erste lauf klappt wie bisher fehlerfrei (da brauche ich das DefaultTableModel auch nicht), aber wenn ich dann die neue Abfrage anzeigen lassen will kracht es an folgender Stelle:

final DefaultTableModel model = (DefaultTableModel)tabelle.getModel();


mit folgender Fehlermeldung:

Exception occurred during event dispatching:
java.lang.ClassCastException: javax.swing.JTable$2
at EingabeFenster$ButtonListener.actionPerformed(EingabeFenster.java:74)

Woran könnte das liegen?

ClassCastException bedeutet, dass das explizite casten an dieser Stelle fehlgeschlagen ist, Du also bei getModel() kein DefaultTableModel bekommst.

Achja und wie bekomme ich die Scrollbalken angezeigt

Vielen Dank für eure Hilfe.

mfg,
Profiler

Du legst die Tabelle in den Viewport einer JScrollPane und fügst die JScrollPane dem Panel hinzu und nicht die Tabelle.
 
Snape hat gesagt.:
ClassCastException bedeutet, dass das explizite casten an dieser Stelle fehlgeschlagen ist, Du also bei getModel() kein DefaultTableModel bekommst.

Ja was der Fehler bedeutet ist mir klar. Was ich wissen wollte ist, wieso das nicht geht.
Die Funktion getModel liefert mir ein TableModel zurück, aber wieso kann ich das nicht auf DefaultTableModel casten?

Das andere werde ich morgen ausprobieren, vielen Dank.

mfg,
Profiler
 
Profiler83 hat gesagt.:
Ja was der Fehler bedeutet ist mir klar. Was ich wissen wollte ist, wieso das nicht geht.
Die Funktion getModel liefert mir ein TableModel zurück, aber wieso kann ich das nicht auf DefaultTableModel casten?
mfg,
Profiler


Weiß ich jetzt auch nicht. Ich arbeite immer mit einem eigenen TableModel, solltest Du Dir auch mal überlegen.
class MyTableModel extends DefaultTableModel
und gut is.
 
Hi,

habs jetzt folgendermaßen gemacht:

Beim Konstruktor der Tabelle den Aufruf von:

tabelle = new JTable(data,spalten);

nach

tabelle = new JTable(new DefaultTableModel(data,spalten));

geändert.

Jetzt funktioniert das Casten.

Und den Fehler mit den Scrollbars hab ich auch behoben. Hatte zwar die Table in die ScrollPane eingefügt, aber dann den Fehler gemacht, trotzdem die Table zu adden.

Vielen Dank für eure Hilfe.

mfg,
Profiler
 
Zurück