JTable: Beim ändern oder löschen ändert sich die ganze Spalte

Tsa

Mitglied
Hey Leute,
ich habe mich gerade gefreut das allles soweit funktioniert, als ich feststellen musste das es doch noch ein kleines Problem gab. Löse ich über ein JPopupMenu einen ActionListener aus, der eine Zelle ändern oder löschen soll, so ändert/löscht er die ganze Spalte. Am Anfang beim editieren nur die eine Zelle, dann jedoch beim Selektieren einer anderen Zeile ändert er auch die Zelle in der Spalte. Beim Löschen ist mir das noch unbegreiflicher, da er 5 Zellen in dieser Spalte in Folge löscht, weitere jedoch erst nach selektieren.
Ich hab leider keine Ahnung wo der Fehler liegen könnte und gebe euch deshalb einfach mal ein paar darin verwickelte Klassen an die Hand.

Das TableModel:
Code:
public class MyTableModel extends AbstractTableModel
{
	private static final long serialVersionUID = -2987215348188188218L;
	private Vector<Vector> daten = new Vector<Vector>();
	private Vector<String> columnNames = new Vector<String>();
	
	public MyTableModel(Vector<Vector> daten, Vector<String> columnNames)
	{
		super();
		this.columnNames = columnNames;
		this.daten = daten;		
	}
	public String getColumnName(int col)
	{
		return columnNames.get(col).toString();
	}
	public int getRowCount()
	{
		return daten.size();
	}
	public int getColumnCount()
	{
		return columnNames.size();
	}
	public Object getValueAt(int row, int col)
	{
	   return ((Vector)daten.get(row)).get(col).toString();
	}
	public boolean isCellEditable(int row, int col)
	{ 
	   return false;
	}
	@SuppressWarnings("unchecked")
	public void setValueAt(Object value, int row, int col)
	{
	    daten.get(row).add(col,(String)value);
	    System.out.println("Setze wert "+value+": "+row+""+col);
	    fireTableCellUpdated(row, col);
	}	
}

Der Frame in der die JTable angezeigt wird:
Code:
public MyFrame() {
		super();
		mouseListener = new JFrameMouse(this);

		fillColumnNamesVector();
		fillRowDataVector();
		table.setModel(new MyTableModel(rowData, columnNames));
		table.getTableHeader().setReorderingAllowed(false);
		
		buchHinzufuegenIt.addActionListener(FrameAction.getBuchHinzufuegen());
		konfigurationIt.addActionListener(FrameAction.getKonfiguration());
		suchenIt.addActionListener(FrameAction.getSuchen());
		
		dateiMenu.add(buchHinzufuegenIt);
		dateiMenu.add(konfigurationIt);
		dateiMenu.add(suchenIt);
		menuBar.add(dateiMenu);

		table.addMouseListener(mouseListener);
		table.setVisible(true);
		JScrollPane scrollbar = new JScrollPane(table);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(700, 500);
		getContentPane().add(scrollbar);
		setJMenuBar(menuBar);
		setVisible(true);
	}
	private void fillColumnNamesVector() {
		columnNames.add("Titel");
		columnNames.add("Autor");
		columnNames.add("ISBN");
		columnNames.add("Verliehen");
		columnNames.add("An Wen");
		columnNames.add("Anzahl");
	}

	private void fillRowDataVector() {
		for (int i = 0; i < 10; i++) {
			

			daten.add("Titel");
			daten.add("Autor");
			daten.add("ISBN");
			daten.add("Verliehen");
			daten.add("An Wen");
			daten.add("Anzahl");

			rowData.add(daten);
		}
	}

	public JFrame getJFrame() {
		return this;
	}

	public JTable getTable() {
		return table;
	}

	public void setTable(JTable newTable) {
		table = newTable;
	}

	public void deleteRow(int row) {
		/**
		 * ToDo: Datenbank Zeile löschen lassen, danach repaint der Table...
		 */
		table.repaint();
	}
	public static Vector<Vector> getRowData(){
		return rowData;
	}
	public static Vector<String> getDaten(){
		return daten;
	}
	public static Vector<String> getColumnNames(){
		return columnNames;
	}
	public void tableRepaint()
	{
		table.repaint();
	}

zum Editieren:
Code:
public VerleihEditierenAction(VerleihEditieren verleihEditieren, MyFrame parent)
	{
		this.verleihEditieren = verleihEditieren;
		this.parent = parent;
	}
	
	public void actionPerformed(ActionEvent arg0)
	{
		if(arg0.getSource() == verleihEditieren.getClose())
		{
			verleihEditieren.close();
		}
		else if(arg0.getSource() == verleihEditieren.getAendern())
		{
			JTable table = verleihEditieren.getTable();
			String newValue = verleihEditieren.getNewValue();
			int atRow = verleihEditieren.getSelectedRow();
			int atColumn = verleihEditieren.getColumn();
			String cache = (String)table.getValueAt(atRow, atColumn+1);
			
			if(!newValue.equals(""))
			{
				table.setValueAt("Verliehen",atRow,atColumn-1);
			}
			table.setValueAt(newValue,atRow,atColumn);
			table.setValueAt(cache,atRow,atColumn+1);
			parent.setTable(table);
		}
	}

Zum Löschen:
Code:
public VerleihLoeschen(MyFrame parent)
	{
		JTable table = parent.getTable();
		String anzahl = (String) table.getValueAt(table.getSelectedRow(),5);
		table.setValueAt("Nicht Verliehen",table.getSelectedRow(),3);
		table.setValueAt("",table.getSelectedRow(),4);
		table.setValueAt(""+anzahl,table.getSelectedRow(),5);
		parent.setTable(table);
		parent.tableRepaint();
	}

Falls ihr weitere Klassen braucht, nur bescheid sagen. Hoffe auf baldige Hilfe :|
Mfg,
Jens
 
Moin,
also mir sind einige Dinge schleierhaft.
- zum Ändern nimmst Du zwar die selectedRow, aber nicht die selectedColumn?
- zum Ändern ist normalerweise nix nötig außer einer Implementierung und Anpassung von isCellEditable, vielleicht noch eine Implementierung von setValueAt.
- ein erneutes Setzen der Tabelle (parent.setTable()) habe ich noch nie gesehen, ist also wohl kaum notwendig, vor allem nicht für diese Zwecke
- ebenso tableRepaint() und table.repaint(). Wenn sich Daten ändern, ruft man fireTableDataChanged auf, wenn sich Spalten/Zeilen ändern und fireTableDataChanged nicht ausreicht, nimmt man fireTableStructureChanged
 
Heyho,
Ja, die selectedColumn ist nicht gewollt, da die Zelle dann beliebig wäre und es sollte immer die gleiche Zelle einer Reihe geändert werden.
Die Implementierung brauchte ich so, da ich mit Vektoren arbeite und das Abstract Table Model dies wohl noch nicht bereitstellte... Ich musste also von Arrays auf Vektoren umschreiben...
Den Rest werd ich mal nachschaun ob es daran gelegen haben sollte ;)
mfg,
Jens

EDIT: Also hat alles nichts gebracht! WEnn ich heute Nacht aus dem Theater zurück bin, aktualisiere ich oben die Code fragmente! :| Hoffe das es weitere Ideen gibt! Danke schonmal Snap :)
 
Zuletzt bearbeitet:
Moin,
also ich verstehe immer noch nicht, was das werden soll. Zum Editieren einer Zelle klickt man üblicherweise hinein und überschreibt/ändert den Inhalt - vorausgesetzt das isCellEditable ist entsprechend angepasst.
Also was SOLL passieren, und was passiert tatsächlich?
 
Hey,
Also isCellEditable is false! Ich schreibe ein Buchverwaltungs Programm und die JTable ist mehr zur Ausgabe da, als das der User selbst etwas darin editiert!
Editieren macht er über Dialoge die sich per JPopupMenu aufrufen lasse. Wenn ich etwas ändere soll dies in der JTable geändert werden und ebenso in der Datenbank.
Was jedoch passiert ist, ich ändere, will in die JTable eintragen und zuerst wird die eine Zelle editiert. Selektiere ich jetzt die nächste REIHE wird die gleiche Spalte in einer anderen Reihe geändert. Dies soll jedoch nicht geschehen, da man dann ja ein weiteres Buch mit den Daten von dem einen Buch bearbeitet. Ebenso verhält es sich mit dem Löschen!
Ich hoffe mein Standpunkt ist klarer geworden, sonst versuch ichs mal mit Screenshots!
MfG,
Jens
 
>Was jedoch passiert ist, ich ändere, will in die JTable eintragen und zuerst wird die eine Zelle editiert. Selektiere ich jetzt die nächste REIHE wird die gleiche Spalte in einer anderen Reihe geändert. Dies soll jedoch nicht geschehen

Bei einem solchen Verhalten liegt der Verdacht sehr nahe, dass es ein Problem mit dem Zusammenspiel von getValueAt und setValueAt gibt bzw. mit der Datenhaltung.
 
Ich glaub ich schreibe es heute einfach noch einmal neu, vielleicht funktioniert es dann ;)
Melde mich dann hier nochmal wie es lief! Danke Snape :)
 
Zurück