Neue Zeile einer JTable nach hinzufügen nicht auswählbar

Hallo Zusammen,

ich erstelle in einer Methode “tabelleerstellen” eine Tabelle.

Hier der Code:

    public void tabelleerstellen() {
           
           
            try{
               
            Class.forName("de.root1.jpmdbc.Driver");
     
            Connection con = DriverManager.getConnection("jdbc:jpmdbc:http://meinedaten);
           
            Statement stmt = con.createStatement();
                   
            ResultSet rs = stmt.executeQuery("SELECT * FROM namen);
           
            Vector data = new Vector();
           
            // Die Titel für das Table
           
            Vector title = new Vector();
                title.add( "Vorname" );
                title.add( "Name" );
                title.add( "Datum" );
     
     
                while(rs.next()) {
                   
                    Vector rowA = new Vector();
               
                    rowA.add(rs.getString("vorname"));
                    rowA.add(rs.getString("name"));
                    rowA.add(rs.getString("date"));
     
                   
                    data.add( rowA );
           
                }
               
                rs.close();
                stmt.close();
                con.close();
               
     
                model = new DefaultTableModel(data, title);
                               
                                table = new JTable(model) {
                                    public boolean isCellEditable(int x, int y) {
                                        return false;
                                    }
                                };
               
               
                                ListSelectionModel selectionModel = table.getSelectionModel();
                                selectionModel.addListSelectionListener(this);
           
                table.setRowSelectionAllowed(true);
     
                        selectionModel.addListSelectionListener(this);
                        unten = new JScrollPane(table);
                        unten.repaint();
                        addItem(unten, 0, 2, 3,1,GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH,150, 150,0,0);
                       
                        table.setAutoCreateRowSorter(true);        
                        table.getTableHeader().setReorderingAllowed( true );        
                        table.getTableHeader().setResizingAllowed( true ); 
                       
            } catch(Exception e1){
     
                System.out.println("Fehlermeldung: "+e1);
     
                }
        }

Während der Ausführung wird die Tabelle in ein JScrollPane eingefügt. Dieses JScrollPane wird dann wiederum in ein JPanel eingefügt.

Bei der ersten Ausführung ist das auch kein Problem. Wenn ich nun aber während der Laufzeit neue Daten in die MySQL-Datenbank schreibe, aus der die Tabelle generiert wird und dann die Methode “tabelleerstellen” erneut aufrufe, aktualisiert er zwar optisch die Tabelle. Ich kann die letzte Zeile aber nicht anklicken.

Die einzelnen Elemente werden im Kopf der Klasse deklariert:

        JTable table;
        JScrollPane unten;
        DefaultTableModel model;

Bei einer Datenänderung wird der folgende Aufruf gestartet:

                tabelleerstellen();
                unten.validate();
                unten.repaint();

Woran liegt es, dass die erste Ausführung das gewünschte Ergebnis bringt, die zweite aber nur teilweise. Ich initialisiere doch die Tabelle, das Model und das JScrollPane jeweils neu bei jedem Methodenaufruf.

Ist das falsch?

Gibt es hier vielleicht jemanden in der Region Münster-Osnabrück, der mich (natürlich gegen Bezahlung) als Java-Tutor bei einigen Themen beraten würde? Dann bitte eine PM.

Viele Grüße,
Sebix

Nach dem du deine GUI das erste mal erställt hast solltest du die JTable nich neu erstellen, sondern der Tabelle nur ein neues TableModel geben. Es hat sich ja nicht die JTable geändert, sonder nur die Daten.

weiters sollten alle änderungen die mit der GUI zu tun haben NUR im Event Dispatcher Thread gemacht werden. An deinem Codeausschnitt kann ich nicht erkennen, ob du dies gemacht hast?

es ist übrigens allgemein humaner, das Tablemodel zu überschreiben für isCellEditable(), eine überschaubare austauschbare Klasse, deren Namen schon Überschreiben suggeriert,
die JTable ist dagegen ein GUI-Schwergewicht, nur im Notfall überschreiben

mit dem Model hast du auch alle Möglichkeiten, kannst bei Bedarf austauschen (wie hier angebracht), kannst Zellen wieder editierbar machen,
die JTable wäre einmal überschrieben nicht mehr zu ändern und die auszutauschen ist (wie hier, auch wenn genauer Fehlergrund vielleicht noch nicht geklärt) vergleichsweise häßlich

Nicht repaint() sonder revalidate() aufrufen. Oder validate nach repaint.

Hallo Zusammen,

Danke erstmal für die Antworten.

Entsprechend dem Hinweis habe ich nun die Nichteditierbarkeit der Zellen über das model realisiert. Allerdings hat das ja nach meinem Verständnis nichts mit meinem Problem zu tun.

Das Thema “Event Dispatcher Thread” sagt mir derzeit nicht viel in der operativen Umsetzung, der arbeitet doch im Hintergrund und sortiert die einzelnen Events nacheinander zur Abarbeitung ein, oder?

Ich denke ich habe da ein Problem mit dem ListSelectionModel, dass ist doch für die Selektion zuständig, oder?

Wenn ich das Fenster in der Größe verändere kann ich auch die letzte (also die neue) Zeile selektieren, jedoch liefert “table.getSelectedRow()” für alle Zeilen die ich auswähle immer “-1” zurück, ab dem Zeitpunkt des hinzufügens der neuen Zeile. Bevor ich etwas ändere liefert es die korrekte Zeile.

Ich habe validate nach repaint gesetzt und es auch mit revalidate versucht, leider keine Änderung.

Hat noch jemand eine Idee, woran es liegen kann?

Viele Grüße,
Sebix

nur am unten-Panel aufgerufen wäre es zu wenig, unten wird irgendwo eingefügt, da ist es wichtig,

überhaupt ein vollständiges Testprogramm! und bedenke wie hilfreich es in meinem Beispiel ist, simple Dummy-Daten statt nicht nachvollziehbarer unnötiger Datenbankabfragen,
solche Dinge sind sehr wichtig, in der Hinsicht bitte auch mit-lernen

public class Test2
    implements ListSelectionListener
{
    private JFrame frame;
    private JTable table;
    private JScrollPane unten;
    private DefaultTableModel model;

    public static void main(String[] args)
        throws Exception
    {
        new Test2();
    }

    public Test2()
        throws Exception
    {
        SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    frame = new JFrame();
                    frame.setSize(400,100);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                }
            });

        for (int i = 0; i < 100; i++)
        {
            Thread.sleep(3000);
            tabelleerstellen();
        }

    }

    public void tabelleerstellen()
    {

        Vector data = new Vector();

        // Die Titel für das Table
        Vector title = new Vector();
        title.add("Vorname");
        title.add("Name");
        title.add("Datum");

        int size = model == null ? 1 : model.getRowCount() + 1;
        for (int i = 0; i < size; i++)
        {
            Vector rowA = new Vector();
            rowA.add("vorname " + i);
            rowA.add("name " + i);
            rowA.add("date " + i);
            data.add(rowA);
        }

        model = new DefaultTableModel(data, title)
            {
                public boolean isCellEditable(int x, int y)
                {
                    return false;
                }
            };

        table = new JTable(model);


        ListSelectionModel selectionModel = table.getSelectionModel();
        selectionModel.addListSelectionListener(this);

        table.setRowSelectionAllowed(true);

        selectionModel.addListSelectionListener(this);
        unten = new JScrollPane(table);
        frame.getContentPane().removeAll();
        frame.getContentPane().add(unten);
        frame.validate();

        // table.setAutoCreateRowSorter(true);
        table.getTableHeader().setReorderingAllowed(true);
        table.getTableHeader().setResizingAllowed(true);

    }

    public void valueChanged(ListSelectionEvent e)
    {
        System.out.println("event: " + e.getFirstIndex());

    }
}

das ein wenig zu deinem Ansatz, besser eh nur model austauschen, dann nix mit validate usw!
auch mit invokeLater (Ausführen in Event-Thread) aber noch nicht alles, nur am Anfang einmal…