JTable Datensatz je nach Auswahl ändern

Hallo, ich habe eine JList mit dynamischen Einträgen. Je nach ausgewähltem Eintrag möchte ich den Datensatz einer JTable ändern. Man könnte diese JList Einträge quasi als “Abteilungen” ansehen.

Die Auswahl der Liste bekomme ich über einen ListSelectionEvent.
Der JTable übergebe ich im Moment noch mein TableModel, indem sich alle Daten befinden. Muss ich jetzt beim erstellen eines Tabelleneintrages die Liste mit übergeben und dann per RowFilter alle Datensätze mit der ausgewählten “Abteilung” anzeigen ? Oder wie würde man das lösen ?

Mein Tabellen Model:

package Model;


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;


import javax.swing.table.AbstractTableModel;


public class DETableModel extends AbstractTableModel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String[] columnNames = { "Filmname", "Gesehen", "Rating","Gekauft" };
	private ArrayList<Object[]> rowData = new ArrayList<Object[]>();
	
	public DETableModel() {
		if(importTable() != null) {
			rowData = importTable();
		}
		
	}


	public void addRow(Object[] obj) {
		rowData.add(obj);
		this.fireTableDataChanged();
	}


	public Object[] getDataFromArrayForRow(int row) {
		Object[] o = rowData.get(row);
		return o;
	}
	
	public void saveTable() {
		try{  


		    FileOutputStream saveFile=new FileOutputStream("resources/table.sav");


		    ObjectOutputStream save = new ObjectOutputStream(saveFile);


		    save.writeObject(rowData);


		    save.close(); 
		    }
		    catch(Exception exc){
		    exc.printStackTrace(); 
		    }
	}
	
	@SuppressWarnings("unchecked")
	private ArrayList<Object[]> importTable() {
		ArrayList<Object[]> readObject = null;
		try{
		    FileInputStream saveFile = new FileInputStream("resources/table.sav");


		    ObjectInputStream save = new ObjectInputStream(saveFile);


		   readObject = (ArrayList<Object[]>) save.readObject();


		    save.close(); 
		    }
		    catch(Exception exc){
		    exc.printStackTrace(); 
		    }
		return readObject;
	}


	public void removeRow(int index) {
		if(index >= 0) {
		rowData.remove(index);
		this.fireTableRowsDeleted(index, index);
		}
	}


	public int getColumnCount() {
		return columnNames.length;
	}


	public int getRowCount() {
		return rowData.size();
	}


	public String getColumnName(int col) {
		return columnNames[col];
	}


	public Object getValueAt(int row, int col) {
		Object[] o = rowData.get(row);
		return o[col];
	}


	@Override
	public Class<?> getColumnClass(int columnIndex) {
		Class<?> classObj = String.class;
		switch (columnIndex) {
		case 1:
			classObj = Boolean.class;
			break;
		case 2:
			classObj = Integer.class;
			break;
		case 3:
			classObj = Boolean.class;
			break;
		}
		return classObj;
	}


	public boolean isCellEditable(int row, int col) {
		return true;
	}


	public void setValueAt(Object value, int row, int col) {


		Object[] o = rowData.get(row);
		o[col] = value;
		fireTableCellUpdated(row, col);
	}
}


table = new JTable(tableModel);```

Das Problem bei dem Ansatz mit dem RowFilter ist auch, dass ich schon einen RowFilter der JTable übergeben habe, damit ich die Tabelle durchsuchen kann nach anderen Columns.

Hmm, ich versteh noch nicht so richtig, was du erreichen möchtest. Einmal schreibst du, du willst je nach ausgewähltem Eintrag in der List den Datensatz einer JTable ändern. Dann willst du beim erstellen eines Tabelleneintrages die Liste mit übergeben und dann per RowFilter alle Datensätze mit der ausgewählten “Abteilung” anzeigen. Was denn nun? Vielleicht kannst du das Problem nochmal genauer beschreiben.

Ersteres. Das zweite war eher eine Idee wie man ersteres umsetzen könnte.
Als Beispiel ein Bild (siehe Anhang).
Je nach Auswahl von (All, Top,Trash,…(dynamisch erstellt)) sollen andere Tabelleneinträge gezeigt werden, eben jene die in den einzelnen Listen erzeugt wurden.

Dann ist aber das

Je nach ausgewähltem Eintrag möchte ich den Datensatz einer JTable ändern.

nicht richtig beschrieben. Weil du willst nicht „den Datensatz ändern“, sondern die in der Tabelle angezeigten Datensätze filtern, also nur die Datensätze anzeigen, welche zu dem gewählten Eintrag passen. Wenn ich das richtig verstanden habe.

Eine Möglichkeit wäre, die Datensätze im TableModel neu einzulesen und nur die Datensätze zu holen, welche zu dem Eintrag passen. Das TableModel aktualisiert dann die View (JTable). Wie werden die Datensätze denn gespeichert? Datenbank, XML, Textdatei…?

EDIT: Ansonsten hätte ich auch den RowFilter der Tabelle empfohlen…

Die Datensätze werden per ArrayList gespeichert die dann per ObjectOutputStream als Datei geschrieben wird.
Also mein weiteres Vorgehen wäre dann (in der ArrayList liegen ObjectArrays für jede Zeile) einfach diesem ObjectArray noch einen identifier zu übergeben(jenen muss ich ja nicht zwangsläufig dann auch in der Zeile anzeigen) und dann bei Auswahl der Liste alle Zeilen anzuzeigen bei denen der identifier mit der Liste übereinstimmt. Das Problem wäre dabei dann nur, dass ich der Tabelle schon einen RowFilter übergebe :

            sorter.setRowFilter(RowFilter.regexFilter("(?i)" + searchString));


… um die Tabelle nach einem String zu durchsuchen. Wie würde man das dann in Einklang bringen ?

Warum ObjectArrays für jede Zeile? Schreib dir doch eine eigene Klasse für deine Datensätze, von denen du dann Objekte erstellst und in der ArrayList sammelst. Und in dieser Klasse hast du dann eine Variable für deine Auswahl. Da kannst du dann ein Integer für die ID deiner Auswahl oder auch ein enum verwenden. Und nach diesen kannst du dann in deinem TableModel filtern und nur die Datensätze in der Tabelle anzeigen, welche du per Auswahl bestimmt hast.

Das kannst du dann auch in dem RowFilter zusammensetzen, also dass nach der Auswahl UND dem Suchwort gefiltert wird.

Ok danke schonmal für die Hilfe. Habe mir ein Objekt RowData erstellt. Dieses hält alle Informationen und hat eine int variable listIndex die per getter und setter erreicht werden kann und implementiert Serializable damit ich das Objekt auch als Datei ablegen kann. Aber ich habe immer noch ein paar Probleme das richtig zu verstehen wie ich das mit dem RowFilter jetzt handhaben muss. Wenn eine neue Row hinzugefügt wird speichere ich momentan den aktuellen listIndex in dem ModelObjekt ab. Wenn jetzt die liste geändert wird muss ich auch die Anzeige ändern, d.h ich muss den RowFilter in meinem ListSelectionListener setzen. Dort setze ich dann erstmal den rowFilter auf “zeige alle Zeilen an mit listIndex x” und dann bei der Suche ändere ich den RowFilter dann auf “zeige alle Zeilen an mit listIndex x und die den String y enthalten”. Nur wie das regex dafür aussehen muss weiß ich noch nicht so ganz.

Du musst mal im Internet suchen, es gibt beim RowFilter auch die Möglichkeit, die Filter mit andFilter zu kombinieren. Ich hatte das mal bei einer Tabelle, die ich nach Vor- und Nachnamen (und sogar noch nach einer dritten Auswahl) gleichzeitig filtern wollte.

Danke habs nun mit RowFilter hinbekommen, sodass sogar bei List Index 0 alle rows angezeigt werden für den Reiter „Alle“ und ansonsten eben nur die listen entsprechenden rows.

Vielen Dank :slight_smile:

Ah ein wenig zu früh gefreut. Das sortieren klappt jetzt schon, jedoch laufe ich dadurch in ein anderes Problem.
Ich habe pro Zeile Spalten für Name, Gesehen, Rating, Gekauft und jetzt noch Listenname(index). Aber zusätzlich dazu speichere ich zu dem Objekt noch drei weitere String und ein Byte Array. Diese Informationen werden in einem „Detail Panel“ angezeigt bei Auswahl der Zeile. Ich hole mir die passenden Daten dazu zurZeit noch so:

RowObject details = tableModel                                    .getDataFromArrayForRow(table.[U]getSelectedRow()[/U]);



Natürlich fällt auf, dass jetzt die Detaildaten nicht mehr richtig angezeigt werden, da durch den RowFilter sich auch die Indizes der Zeile geändert hat und die Details für Zeile x eigentlich im Array an Position y stehen. Nur in der „Alle“ Liste klappt das so natürlich noch.
Gibt es da einen guten Ansatz wie ich die Konzeption über die ArrayList Indizes zu gehen umgehen kann ? Oder gibt es eine Möglichkeit den Index der Zeile zu bekommen wenn alle rows angezeigt würden (zb eine Methode von RowFilter) oder muss ich mir beispielsweise den Namen der Zeile nehmen und dann das ganze Array durch iterieren, um das passende Objekt in der ArrayList zu bekommen ?

Danke für eventuelle Antworten :slight_smile:

Die Methode convertRowIndexToModel hilft dir weiter. Dieser übergibst du die Zeilennummer der View und bekommst die entsprechende Zeile des Model geliefert.

Perfekt so klappt es vielen Dank für diese geniale Methode und die ausdauernde Hilfe :slight_smile: