JTable wird nicht aktualisiert, wenn Filter gesetzt ist

Kim

Mitglied
Hallo,

folgendes Problem:

Ich habe:
Tabelle + DefaultTableModel,
2x RadioButton, mit denen der Filter verändert wird
ein RefreshButton, der die Tabelle aktualisieren soll.

Die Daten stammen aus einer Datenbank. Wenn die Tabelle nun geöffnet ist und in dieser Zeit werden neue Daten in die Datenbank eingetragen, dann soll per Button die Tabelle aktualisiert werden.

Folgendes würde funktionieren, allerdings sind so die zuvor gesetzten Filter nicht gesetzt, was ich aber will 😛:

dispose(); //Schließen
Class.Button.doClick(); // Klick um simulieren, welcher das ganze JFrame neu erstellt


Wenn ich nun auf den Button: "ausRefresh" klicke, dann funktioniert dies auch, ABER nur, wenn "allUsers" geklickt ist und NICHT, wenn 'notAllUser' ausgewählt ist.


Button, zum Aktualisieren:
Java:
ausRefresh.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {					
				 //dispose();                                 //War meine erste Lösung,
				 //Anfragi.anfragi_tabelle.doClick();   //Damit hats geklappt
				
				meinModel = getModel();                
				tabelle.setModel(meinModel);

				tabelle.getColumnModel().getColumn(2)
						.setCellRenderer(new MyCellRenderer());
				
				tabelle.setFillsViewportHeight(true);      //
				setFavSize();                                   // Legt Spaltenbreiten fest
			}
});


Methode, die das Model erstellt/liefert:
Java:
public DefaultTableModel getModel() {

		DefaultTableModel model;
		
		overviewVer = new Verbindung();
		ResultSet rs3 = overviewVer.getResultSet("Select * From Anfragen");

		Vector<String> columnNames = new Vector<String>();
		columnNames.addElement("AnfID");
		columnNames.addElement("Klient");
		columnNames.addElement("Problem");
		columnNames.addElement("Eingang");
		columnNames.addElement("Bearbeiter");
		columnNames.addElement("Lösung");
		columnNames.addElement("Abschluss");

		Vector<Vector<Object>> data = new Vector<Vector<Object>>();
		Vector<Object> c;

		
		try {
			while (rs3.next()) {
				
				c = new Vector<Object>();

				for (int i = 1; i <= 7; i++) {

					c.addElement(rs3.getObject(i));
				}

				data.addElement(c);
			}
		} catch (SQLException e) {
			
		}
		
		model = new DefaultTableModel(data, columnNames) {

			private static final long serialVersionUID = 1L;

			// Standard Methode wird überschrieben, sodass die Zellen nicht mehr
			// Editierbar sind
			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}

		};
		
		return model;

	}


'allUsers' und 'notAllUsers' sind in der selben Gruppe.

RadioButton, alle Benutzer:
Java:
allUsers.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				einzelUser.setEnabled(false);
				/*
				 * Filter 3: lässt alles durch
				 */
				filters.set(2, RowFilter.regexFilter("", 1));
				filter = RowFilter.andFilter(filters);
				rowSorter.setRowFilter(filter);

			}
});

RadioButton, einzelne Personen:
Java:
notAllUsers.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				einzelUser.setEnabled(true);
				String zeichen = "";
				String[] splitName = einzelUser.getSelectedItem().toString()
						.split(",");
				for (int i = 0; i < benutzer.length; i++) {
					if (benutzer[i][0].equalsIgnoreCase(splitName[0])
							&& benutzer[i][1].equalsIgnoreCase(splitName[1]
									.trim())) {
						zeichen = benutzer[i][2];

					}
				}
				/*
				 * Filter 3: Filtert benutzer
				 */

				filters.set(2, RowFilter.regexFilter(zeichen, 1));
				filter = RowFilter.andFilter(filters);
				rowSorter.setRowFilter(filter);
				
				
			}
});


PS: wie kann man beiträge editieren?
 
Hallo erst einmal.
Dein Code ist schwer zu lesen, weil du wenig lokale Variablen benutzt. So weiß ich nicht genau, wie die Dinge zusammenhängen bzw. welchen Typ die Variablen eigentlich haben.

Aber mal unabhängig davon das Ganze betrachtet; Dann ist dein Problem, dass deine Tabelle nach einem Klick auf einen entsprechenden Filter-Button nicht korrekt gefiltert wird?
Du sagst es geht nach beim "Alle"-Filter aber nicht beim anderen. Da beide Funktionen sehr ähnlich sind, vermute ich dass es am RegEx liegt. Hast du dir
Code:
zeichen
(das du als RegEx-Filter setzt) schonmal angesehen? Womöglich ist es gar kein gültiges RegEx.

Kim hat gesagt.:
PS: wie kann man beiträge editieren?
Am unteren Ende deines Posts gibt es einen Button "Ändern". Aber da dein Forentitel "Wartet auf Aktivierung" ist, kann es auch sein, dass du das noch nicht darfst 🙂 (Weiß ich aber nicht).
 
Hallo erst einmal.
...
[1]
Aber mal unabhängig davon das Ganze betrachtet; Dann ist dein Problem, dass deine Tabelle nach einem Klick auf einen entsprechenden Filter-Button nicht korrekt gefiltert wird?

[2]
Du sagst es geht nach beim "Alle"-Filter aber nicht beim anderen. Da beide Funktionen sehr ähnlich sind, vermute ich dass es am RegEx liegt. Hast du dir
Code:
zeichen
(das du als RegEx-Filter setzt) schonmal angesehen? Womöglich ist es gar kein gültiges RegEx.
...

[1] : Korrekt, es sind anstatt z.B. 4 Datensätze nur 3 !

[2]: der "Alle"-Filter sieht so aus: filters.set(2, RowFilter.regexFilter("", 1))
-> bedeutet, er soll alles durchlassen, was nicht dieser Zeichenkette in Spalte 2 entspricht.

In meiner 2. Spalte steht zum Beispiel: "aa" ... wenn ich nun manuell
Code:
filters.set(2, RowFilter.regexFilter("aa", 1))
eingeb, fehlt auch 1 Datensatz (welcher auch zuvor fehlte)

Wenn ich mein Fenster mit der Tabelle schließe und wieder öffne, werden alle Datensätze angezeigt, egal welche Filter ich setze!
 
Hallo. Ich habe mal dieses minimale Programm ausprobiert und da funktioniert es (denke ich) wie gewünscht:
Java:
public class Dummy
{
    public static void main( String[] args )
    {
        // Tabelle
        final JTable table = new JTable(new Object[][] {
                {"a",   "2",   "3"},
                {"aab",  "22",  "33"},
                {"bbvc", "222", "333"}               
        }, new Object[] {
                "Eins", "Zwei", "Drei"     
        });
        
        // Sorter
        final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(
                table.getModel());
        table.setRowSorter(sorter);
        
        // Filter-Buttons
        final JRadioButton btnAll = new JRadioButton("Alle");
        btnAll.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed( ActionEvent e )
            {
                // RegEx akzeptiert alles (für Spalte 0)
                sorter.setRowFilter(RowFilter.regexFilter("", 0));
                // sorgt dafür dass die Sortierung aufgehoben wird,
                // das ist aber nicht nötig
                sorter.setSortKeys(null);
            }
        });
        
        final JRadioButton btnAs = new JRadioButton("Nur 'A'");
        btnAs.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed( ActionEvent e )
            {
                // RegEx akzeptiert alles was in Spalte 0 mit einem kleinen 
                // 'a' anfängt
                sorter.setRowFilter(RowFilter.regexFilter("a\\w*", 0));
                sorter.setSortKeys(null);
            }
        });
        
        // BtnGruppe damit nur ein Radiobutton gleichzeitig aktiv ist
        ButtonGroup btnGroup = new ButtonGroup();
        btnGroup.add(btnAll);
        btnGroup.add(btnAs);
        btnGroup.setSelected(btnAll.getModel(), true);
        
        // GUI
        final JFrame frame = new JFrame("Table Filter Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(new JScrollPane(table), BorderLayout.CENTER);
        frame.add(btnAll, BorderLayout.EAST);
        frame.add(btnAs, BorderLayout.WEST);
        
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                frame.pack();
                frame.setVisible(true);
            }
        });                                                     
    } //main
}
Vielleicht hilft es dir dabei den Fehler oder die Ungereimtheit zu finden. Aber eines noch:
Kim hat gesagt.:
-> bedeutet, er soll alles durchlassen, was nicht dieser Zeichenkette in Spalte 2 entspricht.
Das Filterkriterium gibt an, was angezeigt werden soll, nicht was ausgenommen wird. Sprich wenn ich "a" setze zeigt er alles an, was mit "a" beginnt. Daher wirkt auch "", weil jeder Text mit dem leeren String beginnt 🙂

Kim hat gesagt.:
Wenn ich mein Fenster mit der Tabelle schließe und wieder öffne, werden alle Datensätze angezeigt, egal welche Filter ich setze!
Ist das nun dein Problem und es geht gar nicht um das Filtern an sich? Es kommt dann nämlich vor allen drauf an, was beim Schließen, bzw. Wiederanzeigen des Fensters gemacht wird. Wenn das Fenster zB immer neu aufgebaut wird oder das Tabellenmodell neu gesetzt wird, kann das durchaus sein. Wenn man das Fenster wahlweise ein- und ausblenden kann, ohne dessen Zustand zu beeinflussen, dann reicht
Code:
setVisible(true/false)
.

PS: Man muss als RegEx-Filter gar kein ganzes RegEx angeben so wie ich mit "a\\w*". Nur "a" hat den gleichen Effekt, zumindest in dem Testprogrämmchen...
 
Das Filterkriterium gibt an, was angezeigt werden soll, nicht was ausgenommen wird. Sprich wenn ich "a" setze zeigt er alles an, was mit "a" beginnt. Daher wirkt auch "", weil jeder Text mit dem leeren String beginnt
Du hast natürlich recht, hatte mich verschrieben.

Ich hab das Problem vll noch nicht verständlich genug beschrieben:

Also ich habe eine Datenbank, welche die Daten für meine Tabelle, bzw, das Model enhält.

Wenn ich nun meine Tabelle öffne, dort z.b den Filter Setze, "aa" in spalte 1 (Tats. Spalte1), dann während ich meine Tabelle auf hab, wird ein neuer Datensatz in die Datenbank eingefügt, welcher auf den gesetzten Filter passt. Wenn ich jetzt den Aktualisierungs Button drücke, soll auch dieser Datensatz angezeigt werden. DIES tut er aber nicht, sondern er wird nur angezeigt, wenn ich den Filter auf "" setz!

Hinter meinen Akutalisierungs Button ist der der selbe Code, es unterscheidet sich nur in folgendem:

mein AktualisierungsButton, macht
kein
Code:
JTable tabelle= new JTable(meinModel)
,
sondern:
Code:
meinModel = getModel();   
		 tabelle.setModel(meinModel);

und:
die filter werden auch nicht erstellt/gesetzt, da diese ja so bleiben sollen, wie vor der Aktualisierung


angenommen, es wurde nun ein Datensatz eingefügt, ich aktualisiere, und seh ihn NICHT mit gesetztem filter, dann schließ ich mein Fenster und erstell es neu, SETZE dann den gleichen Filter, wird dieser Datensatz angezeigt

....


Mach ich, wie vorgeschlagen
Code:
setVisible(false); set Visible(true);
, dann wird der neue Datensatz angezeigt, dafür fehlt ein anderer.


Danke für deine Hilfe
kim

ps. konnte nicht schneller antworten, wegen inet probs
 
Hallo.

Ok, also liegt das Problem gar nicht am Filter, sondern daran, dass das Modell beim Aktualisieren den Filter verliert?

Ich kann mir schon vorstellen, dass nach einem
Code:
setModel()
die Tabelle alle Filter (auch Sorter etc) verwirft, weil sich das Modell ja theoretisch grundlegend ändern kann.
D.h. für dich, dass du entweder
Code:
setModel()
vermeiden musst oder den Zustand der Tabelle (in diesem Fall vor allem die Filter), danach neu setzen musst:
Java:
onRefresh:
// Filter (Sorter) speichern
tabelle.setModel( neuesModell );
// Filter (Sorter) neu setzen

Da sich das Modell der Tabelle nicht ändert, sondern nur der Inhalt neu geladen wird, könntest du deine Refresh-Methode anders aufbauen. In Pseudocode etwa so:
Java:
onRefresh:
MyTableModel model = (MyTableModel) myTable.getModel();
// neue Daten aus DB holen
model.setData( datenAusDB );

Hierbei ist es dann auch wichtig, dass deine TableModel-Implementierung ein entsprechendes Ereignis auslöst, wenn sich die Daten geändert haben. Wenn du von AbstractTableModel erbst, wäre die beste Möglichkeit
Code:
fireTableDataChanged()
aufzurufen. Die von mir erdachte Methode
Code:
setData()
könnte dann wie folgt aussehen:
Java:
public final class MyTableModel extends AbstractTableModel
{
    // ...
    private Object[][] data;
    
    public void setData( Object[][] newData )
    {
        this.data = newData;
        this.fireTableDataChanged();
    }
Bei einer solchen Handhabe sollten Filter etc. nicht verworfen sondern beibehalten werden.
 
Hallo Leute, ich bin gerade dabei ein Programm zu schreiben, womit ich eine SQL-Abfrage machen kann und mein Ergebnis in einer JTable reinschreiben lasse.

Mein Problem ist aber jetzt, dass meine Tabelle so aussieht, dass ich die erste Zeile mehrmals in meine Tabelle eingefügt bekomme.

In meiner Schleife muss wohl etwas falsch sein, dass der mir die nächste Zeile nicht in die Tabelle eintragen kann :-(

Wenn ich eine konsolen Ausgabe mit >System.out.println()< mache kann ich alle meine Zeilen sehen, nur dass sie nicht untereinander sondern nebeneinander gestellt werden.

Also was ich in der Konsole sehe ist:
[66118271 , Meier, Hans, 1959-01-01 00:00:00.0, 99992207 , Meier, Hans, 1959-01-01 00:00:00.0, 67002002 , Meier, Hans, 1959-01-01 00:00:00.0, 58000000 , .....das alles ist in einer Zeile...

hier ist die 1. Spalte meine Auftragsnr., die 2. Spalte ist der name, die 3. Spalte Vorname und die 4. Spalte ist das Geburtsdatum.

in Meiner Tabelle sehe ich aber immer nur "66118271 , Testhansel, ÖÄÜßöäü, 1959-01-01 00:00:00.0" und das so oft wie viele Zeilen ich eigentlich haben. ;(


Ich zeige euch mal mein Code, es wird wohl ein dummer Fehler sein, auf das ich leider nicht komme :-(
.

Java:
	  rs.last();
	 rows = rs.getRow(); //zeigt wie viele Zeilen ich habe
	 rs.beforeFirst();
						
							
							 
 ResultSetMetaData rsmd = rs.getMetaData();// fuer die Spalten
							   
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,								ResultSet.CONCUR_UPDATABLE);
							
						
							
							
	spalten = rsmd.getColumnCount();// das ist ein int, was erstmal auf gesetzt ist
	 columnNames = new Vector<String>();
	for(int is = 1; is<=rsmd.getColumnCount();is++){
	columnNames.addElement( rsmd.getColumnName(is)+newline);
							}
								
							    
							  
    Vector<String> rowZeile =new Vector<String>(); 

	while (rs.next()) {
								
	 for(int ic=1; ic<(rsmd.getColumnCount())+1; ic++){
		rowZeile.addElement(rs.getString(ic));
	}
		  System.out.println(rowZeile);
	  }

	@SuppressWarnings("rawtypes")
	Vector<Vector> rowData = new Vector<Vector>();
		//Hier gibt es ein Problem!!!!
							
							
							
	 for(int i=0; i<rows; i++){
	// System.out.println(rowZeile + newline);
						
	  rowData.addElement(rowZeile);
			
	}		
							 
 table = new JTable(rowData, columnNames);
 scrollPane = new JScrollPane(table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
....usw

Ich würde mich freuen, wenn ihr mir auchnur einen Tipp geben könnt 🙁
 
1. Was spricht dagegen einen neuen Thread zu dem Thema aufzumachen? ;-)
2. Ist der Code ja nur chaotisch und man kann froh sein, dass überhaupt was angezeigt wird ;-)
3. Du steckst alle Datensätze nacheinanderer in den Vector rowZeile und diesen Vector steckst Du mehrfach in den Vector rowData, d.h. wenn Du die Spaltenzahl Deiner Tabelle erweitern würdest, würde man die weiteren Datensätze in den nachfolgenden Spalten sehen.
--> Du musst jeden Datensatz in einen neuen Vector stecken und diese Vectoren in dem Vector rowData sammeln, dann bekommst Du die Datensätze auch korrekt angezeigt.
 
Stimmt, ich hätte ein neues Thema öffnen müssen 😳
Werde ich beim nächsten mal definitiv machen 🙂

Also mein Programm muss 4 Spalten und mehrere Zeilen haben und du hast recht es ist richtig kaotisch. Ich versuche gerade das mit mehrere Vectoren zu machen, aber irgendwie komme ich nicht dahinter :-(
 
Die Reihenfolge ist einfach falsch. Musst Dir einfach nur überlegen wie da von "Hand" vorgehen würde.

1. Erzeuge einen Vector der die gesamten Daten aufnehmen kann
2. Lese die nächste Zeile aus (solange es noch was zu lesen gibt)
3. Erzeuge einen Vector für diese Zeile und befülle in mit den Werten
4. Stecke diesen Zeilenvector aus Schritt 3 in den Gesamtdatenvektor aus Schritt 1
5. gehe zu Schritt 2
 

Zurück
Oben