JTable bei löschen oder hinzufügen eines Wertes aktualisiere

Status
Nicht offen für weitere Antworten.

Aetsch

Mitglied
Hi,

ich brauch mal wieder Eure Hilfe. Ich habe in meinem GUI ein JTable angelegt. Wenn ich Eintragungen lösche wirds auch getan, aber ich schaffe es nicht das das JTable aktualisiert. Sitze da schon seit Stunden dran bekomme das aber nicht hin :x

Was kann ich da machen?

(Kann mir noch jemand erzählen wie ich im ActionListener auf Variablen zugreifen kann die nicht final sind?)

Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import java.io.*;

public class MainMenu extends JFrame{

  Auto a1 = new Auto();

  public MainMenu(String kennzeichen){
    super("Spritkosten Manager");
    
    //Auto laden !!!!
    try{
      ObjectInputStream in = new ObjectInputStream(new FileInputStream(kennzeichen + ".car"));
      a1 = (Auto)in.readObject();
      System.out.println("Laden erfolgreich");

    }catch(IOException e){
      System.out.println("Da ging was mit dem Laden nicht");
    }catch(ClassNotFoundException ce) {
      System.out.println("Da ging was mit den Klassen nicht");
    }

    //JFrame geht los :)
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    //JPannels initialisieren
    JPanel kennzeichenAnzeige = new JPanel();
    kennzeichenAnzeige.setLayout(new FlowLayout(FlowLayout.CENTER));

    JPanel options = new JPanel();
    options.setLayout(new FlowLayout(FlowLayout.CENTER));

    final JPanel tabelle = new JPanel();
    tabelle.setLayout(new FlowLayout());

    JPanel funktionen = new JPanel();
    funktionen.setLayout(new GridLayout(8,2));
    
    //JPanel kennzeichenAnzeige
    JLabel JKennzeichen = new JLabel(kennzeichen);
    kennzeichenAnzeige.add(JKennzeichen);
    
    //JPanel options
    JButton speichern = new JButton("Speichern");
    JButton hilfe = new JButton("Hilfe");
    options.add(speichern);
    options.add(hilfe);
    
    //JPanel tabelle
    String[] spalten = {"Nr", "km-Stand", "gefahren", "getankt", "Preis/l", "GesamtPreis", "l/100km", "Reichw.", "Datum", "Bem."};
    String[][] daten = macheDaten(a1);

    final JTable Jtabelle = new JTable (daten, spalten);
    JScrollPane scrollPane = new JScrollPane(Jtabelle);
    tabelle.add(scrollPane);

    //JPanel funktionen
    JButton neu = new JButton("Neuer Eintrag");
    JButton loeschen = new JButton("Letzten Eintrag löschen");
    JButton statistiken = new JButton("Statistik für Tankung: ");
    JButton statistikenGesamt = new JButton("Gesamtstatistik");
    JLabel platzHalter1 = new JLabel("");
    JLabel platzHalter2 = new JLabel("");
    JLabel platzHalter3 = new JLabel("");
    JLabel platzHalter4 = new JLabel("");

    //ActionListeners
    final int anzahl = a1.getAnzahl();
    final Auto a2 = a1;
    
    statistiken.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        int tankungNr = anzahl-Jtabelle.getSelectedRow();
        if(tankungNr == 0){
          JOptionPane.showMessageDialog(null, "Basisdatensatz, kann nicht genutzt werden !", "Fehler", JOptionPane.INFORMATION_MESSAGE);

        }else if(Jtabelle.getSelectedRow() != -1){
          System.out.println(tankungNr);
          Statistik stats = new Statistik(a2, tankungNr);
          stats.setVisible(true);
        }else{
          JOptionPane.showMessageDialog(null, "Bitte eine Tankung anwählen !", "Fehler", JOptionPane.INFORMATION_MESSAGE);
        }
      }});

    statistikenGesamt.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        StatistikGesamt gesamt = new StatistikGesamt(a2);
        gesamt.setVisible(true);
      }});

    loeschen.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        loescheTankung();
        repaint();
      }});

    funktionen.add(neu);
    funktionen.add(platzHalter1);
    funktionen.add(loeschen);
    funktionen.add(platzHalter2);
    funktionen.add(statistiken);
    funktionen.add(platzHalter3);
    funktionen.add(statistikenGesamt);
    funktionen.add(platzHalter4);

    //JPanels anzeigen lassen
    add(kennzeichenAnzeige, BorderLayout.NORTH);
    add(options, BorderLayout.SOUTH);
    add(tabelle, BorderLayout.EAST);
    add(funktionen, BorderLayout.WEST);
    super.pack();
  }
  private void loescheTankung(){
    a1.loescheTankung();
  }
 
hmm, kann es sein, dass du loescheTankung() & Co gar nicht gepostet hast?

nett aber, dass du viel sinnlosen Kram wie

JButton statistiken = new JButton("Statistik für Tankung: ");
JButton statistikenGesamt = new JButton("Gesamtstatistik");
JLabel platzHalter1 = new JLabel("");
JLabel platzHalter2 = new JLabel("");
JLabel platzHalter3 = new JLabel("");
JLabel platzHalter4 = new JLabel("");

postest, schön das Forum vollkleistern...

-------


evtl. sind dir bisher Befehle wie
fireTableDataChanged() ;
unbekannt? (siehe API TableModel)
 
Ich habs editiert wird Dir aber nicht sehr viel bringen....

Aber mach Dir bitte wegen den paar Zeilen nicht ins Hemd. Ich denk man soll hier so viel Code posten wie geht :meld:
 
ja, z.B. loescheTankung().....
aber auf keinen Fall auch nur eine unnötige Zeile

-------
private void loescheTankung(){
a1.loescheTankung();
}

ist ja schon wieder lustig, also falls du es dir nicht denken kannst:
poste doch bitte mal Quellcode von a1.loescheTankung();

und was ist Auto überhaupt, eine JTable, eine TableModel, ...?


wenn ich mir aus deinem riesigen Wirrwarr die beiden einzigen interessanten Zeilen

String[][] daten = macheDaten(a1);
final JTable Jtabelle = new JTable (daten, spalten);

heraussuche, dann nehme ich mal an, dass es die JTable und nicht mal das daten-Array besonders interessiert,
ob sich in dem fremden Auto-Objekt was ändert 😉

damit sich die JTable ändert, musst du deren Daten neu setzen!
 
poste doch bitte mal Quellcode von a1.loescheTankung();

Code:
  public void loescheTankung(){
    tankungen.remove(tankungen.size()-1);
    tankungenArray = (Tankung[])tankungenToArray();
  }

Auto ist eine Klasse wo ich die Autos inkl. Tankungen drin speicher. Die Tabelle ist ein JTable.

Mit loescheTankung() löscht der die letzte Tankung die mit a1 getätigt wurde aus der ArrayList. Die Objektmethoden prüfen ob das Array aktuell ist und falls nicht erstellen dann aus der ArrayList ein Array damit ich damit arbeiten kann. Eine Tankung ist ein Objekt in der ArrayList/dem Array.

Ich habs jetzt mal ein bissl abgeändert funzt aber noch nicht:

Code:
public class MainMenu extends JFrame{

  Auto a1 = new Auto();
  String[][] daten = macheDaten(a1);
  public MainMenu(String kennzeichen){
.
.
.
  }
}

  private void loescheTankung(){
    a1.loescheTankung();
    daten = macheDaten(a1);
  }

und macheDaten():

Code:
  private String[][] macheDaten(Auto a1){
    String daten[][] = new String[a1.getAnzahl()+1][10];

    daten[a1.getAnzahl()][0] = "0";
    daten[a1.getAnzahl()][1] = Integer.toString(a1.getAnfangsKilometer());
    daten[a1.getAnzahl()][2] = "0";
    daten[a1.getAnzahl()][3] = "0";
    daten[a1.getAnzahl()][4] = "0";
    daten[a1.getAnzahl()][5] = "0";
    daten[a1.getAnzahl()][6] = "0";
    daten[a1.getAnzahl()][7] = "0";
    daten[a1.getAnzahl()][8] = "0";
    daten[a1.getAnzahl()][9] = "Anfangsbestand";

    if(a1.getAnzahl() != 0){
      for (int i = 1; i <= a1.getAnzahl(); i++){
        daten[a1.getAnzahl()-i][0] = Integer.toString(i);
        daten[a1.getAnzahl()-i][1] = Integer.toString(a1.getKilometerstand(i));
        daten[a1.getAnzahl()-i][2] = Integer.toString(a1.getGefahreneKM(i));
        daten[a1.getAnzahl()-i][3] = Double.toString(a1.getGetankteLiter(i));
        daten[a1.getAnzahl()-i][4] = Double.toString(a1.getLiterPreis(i));
        daten[a1.getAnzahl()-i][5] = Double.toString(a1.getGesamtPreis(i));
        daten[a1.getAnzahl()-i][6] = Double.toString(a1.get100KMPreis(i));
        daten[a1.getAnzahl()-i][7] = Integer.toString(a1.getReichweite(i));
        daten[a1.getAnzahl()-i][8] = a1.getDatum(i);
        daten[a1.getAnzahl()-i][9] = a1.getKommentar(i);
      }
    }else{

    }
    return daten;
  }

Das ist so ein wirrwar weil ich das aktuellste oben in der ArrayList haben will 😉
 
alles schon gar nicht schlecht, aber geht der JTAble immer noch am A. vorbei

versuche
((DefaultTableModel) Jtabelle .getModel()).setDataVector(newData,spalten);

wobei du natürlich auf die Tabelle und die Spalten außerhalb des Konstruktors zugreifen musst
(Exemplarvariablen wie a1!)
 
Sry ich versteht nicht ganz was Du meinst.

Wenn ich die Zeile so übernehme und "final JTable Jtabelle = new JTable (daten, spalten);" damit ersetze (newData noch gegen daten ausgetauscht) nimmt erst nicht. "(DefaultTableModel)Jtabelle.getModel().setDataVector(daten,spalten);" is not a Statement.

Ich bin im programmieren noch ein newbie und hab mir swing gestern selbst bei gebracht...
 
final JTable Jtabelle = new JTable (daten, spalten);
bleibt wie es ist, warum etwas funktionierendes im Konstruktor ändern?

im ActionListener willst du doch was tun/ ändern,
da musst du neue Daten setzen mit dem angegeben Befehl
 
So ich hab jetzt:

Code:
public class MainMenu extends JFrame{

  Auto a1 = new Auto();
  String[] spalten2 = {"Nr", "km-Stand", "gefahren", "getankt", "Preis/l", "GesamtPreis", "l/100km", "Reichw.", "Datum", "Bem."};
  String[][] daten2 = macheDaten(a1);
  
  public MainMenu(String kennzeichen){
.
.
.
    loeschen.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        loescheTankung();
        a1.speicherAuto(a1);
        ((DefaultTableModel) Jtabelle .getModel()).setDataVector(daten2,spalten2);
        
        repaint();
      }});
.
.
.
}

  private void loescheTankung(){
    a1.loescheTankung();
    daten2 = macheDaten(a1);
  }

Was mach ich noch falsch? Wenn ich nach dem löschen das Programm neu starte ist der Eintag weg so wie es sein soll. Trotzdem bekomme ich beim Löschen folgende Fehlermeldung: (Zeile 106 ist die mit Deinem Vorschlag)

Code:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JTable$1
 at MainMenu$3.actionPerformed(MainMenu.java:106)
 at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1849)
 at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2169)
 at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
 at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
 at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
 at java.awt.Component.processMouseEvent(Component.java:5488)
 at javax.swing.JComponent.processMouseEvent(JComponent.java:3093)
 at java.awt.Component.processEvent(Component.java:5253)
 at java.awt.Container.processEvent(Container.java:1966)
 at java.awt.Component.dispatchEventImpl(Component.java:3955)
 at java.awt.Container.dispatchEventImpl(Container.java:2024)
 at java.awt.Component.dispatchEvent(Component.java:3803)
 at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
 at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3892)
 at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
 at java.awt.Container.dispatchEventImpl(Container.java:2010)
 at java.awt.Window.dispatchEventImpl(Window.java:1766)
 at java.awt.Component.dispatchEvent(Component.java:3803)
 at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)

 at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:234)
 at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
 at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
 
final JTable Jtabelle = new JTable (daten, spalten);

erzeugt intern kein DefaultTableModel sondern ein anderes,
das ist ungünstig,

ersetze also doch
final JTable Jtabelle = new JTable (daten, spalten);
im Kontruktor durch:

DefaultTableModel myModel = new DefaultTableModel(daten,spalten);
final JTable Jtabelle = new JTable (myModel);

-------

dann bräuchstest du übrigens die Tabelle nicht mehr speichern
sondern nur das TableModel und kannst später auch mit

myModel.setDataVector(daten2,spalten2);

die Daten setzen
 
*knuuuutscha* ES GEHT !!!!!!!

DANKE !!!!!!!!!! 🙂


Aber ein paar Fragen habe ich dennoch:

Wofür ist das DefaultTableModel denn gut? Also was ist da so anders im Gegensatz zum normalen JTable?

"myModel.setDataVector(daten2,spalten2);" damit sage ich ja dem DefaultTableModel das er sich aktualisieren soll. Also löscht der alle Daten aus dem table raus und baut das von Grund auf neu?

(Sorry aber) wieso kann ich im ActionListener nur mit Variablen arbeiten die final sind? Der Compiler sagt weil ich hier eine anonyme Klasse habe, soweit so gut, weiß ich auch, aber wieso können anonyme Klassen nicht mit non-final Variablen arbeiten?
 
> Also löscht der alle Daten aus dem table raus und baut das von Grund auf neu?

die Table hat keine Daten sondern fragt bei allen Operationen das Model nach den Daten,
siehe Tutorials/ Lehrbücher, werde das hier nicht vertiefen

----

der ActionListener muss auf jeden Fall die JTable-Refernz kopieren und in einer internen Variablen speichern,
denn der wird ja erst ausgeführt wenn der Konstruktor und dessen lokale Variable längst Geschichte sind,

warum Java da nicht aus einer normalen Variable kopieren kann verstehe ich auch nicht,
vielleicht dient das als Hinweis für den Programmierer,
damit der nicht denkt, dass er (in deinem Code-Beispiel) am Ende des Konstruktors noch die JTable-Variable ändern kann und der ActionListener dies mitbekommt
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben