# Jtable wird nicht aktualisiert



## sirair (8. Apr 2010)

Hallo,

habe hier ein kleines Beispiel aufgebaut, ist zwar nicht ganz sinnvoll, aber sollte erstmal vom Prinzip her stimmen. Ich bekomme die jtable nicht aktualisiert. Habe vier Klassen: Controller, Model, User, View. Der Model wird benachrichtigt, sobald sich der User geändert hat, in dem Fall sein Name. Rufe dann in der update Funktion der Klasse Model die Funktion fireTableDataChanged() auf. Allerdings wird die Table nicht aktualisiert.



```
import javax.swing.JFrame;

public class Controller extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public Controller() {
		setContentPane(new View());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Controller();

	}


import java.util.Observable;
import java.util.Observer;

import javax.swing.table.DefaultTableModel;

public class Model extends DefaultTableModel implements Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private User u;

	public Model() {
		String[] vColumnNames = { "Name" };
		setColumnIdentifiers(vColumnNames);

		u = new User("TestUser");

		u.addObserver(this);
		addRow(new String[] { u.getName() });
	}

	// TODO Auto-generated constructor stub

	@Override
	public void update(Observable arg0, Object arg1) {
		fireTableDataChanged();
		// TODO Auto-generated method stub

	}

	public User getUser() {
		return u;
	}

import java.util.Observable;

public class User extends Observable{
	private String name;

	public User(String name) {
		this.name = name;
		// TODO Auto-generated constructor stub
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public void update(){
		setChanged();
		notifyObservers();
	}
}


import java.awt.BorderLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class View extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTable table;

	public View() {

		table = new JTable(new Model());
		JScrollPane p = new JScrollPane(table);
		add(p, BorderLayout.CENTER);

		JButton b = new JButton(ACTION_RENAME);
		b.setText("Rename");
		add(b, BorderLayout.NORTH);
		// TODO Auto-generated constructor stub
	}

	private Action ACTION_RENAME = new AbstractAction() {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			((Model) table.getModel()).getUser().setName("Neuer");
			((Model) table.getModel()).getUser().update();
			// TODO Auto-generated method stub

		}
	};
}

}


}
```


----------



## SlaterB (8. Apr 2010)

was sollte denn deiner Meinung nach bei
fireTableDataChanged();
passieren?
soll das Model und die JTable den geänderten Username anzeigen?

das geht so nicht, du hast den String name vom User heraus in ein String[] kopiert/ übertragen,
Strings sind unveränderlich, 
in User könnte höchstens einer String-Variablen ein neuer Wert zugewiesen werden, aber das interessiert doch andere Stellen nicht, die auf den Ursprungstring verweisen

Beispiel:

```
String a = "test";
String b = a;

a = "neu";
// b zeigt immer noch auf "test"
```

du hast drei Möglichkeiten,
1. du steckst den User oder ein anderes höheres Objekt in das Anfangs-Array für das TableModel,
ein Objekt welches geändert werden kann und dessen toString() immer den aktuellen Wert liefert
2. du baust ein intelligenteres Model, ohne Array oder Row, sondern mit überschriebener getValueAt(i,j)-Methode, 
diese könnte komfortabel auf den User zugreifen und diverses von dem zurückgeben
3. in der update-Methode tatsächlich das Model ändern, die alte Row entfernen, eine neue mit den aktuellen User-Daten einfügen


----------



## André Uhres (8. Apr 2010)

sirair hat gesagt.:


> sollte erstmal vom Prinzip her stimmen.


Das hängt ganz davon ab, von welchem Prinzip du sprichst  . Versuch's mal mit setValueAt, statt fireTableDataChanged, etwa so:

```
setValueAt(((User) arg0).getName(), 0, 0);
```


----------



## sirair (8. Apr 2010)

der Model wird zwar aktualisiert, aber nicht die JTable. Kannst du bitte ein Beispiel für die erste Möglichkeit geben.


----------



## SlaterB (9. Apr 2010)

wie wärs mit der einen Code-Zeile von André Uhres, das scheint doch das einfachste


----------



## sirair (9. Apr 2010)

gibts vielleicht Beispiele wie es perfekt geht?


----------



## SlaterB (9. Apr 2010)

was heißt schon perfekt?
zu der von mir präferierten Art hier ein Beispiel:

JavaReference.com : Java, J2EE, Examples, Articles, Forum, Books, News : Example -> Creating simple JTable using AbstractTableModel

beachte wie das TableModel hauptsächlich einen Vektor mit komplexen Objekten enthält,
die getValueAt-Methode bestmmt ein MachineData-Objekt und je nach Index wird eines dessen Attribute zurückgegeben

auf diese Weise kann man mit den gleichen Daten wie im restlichen Programm arbeiten 
ohne alles in eine für die Tabelle passende Struktur (zweidimensionales Schachbrett) zu kopieren


----------



## Michoel (10. Apr 2010)

hi,

vielleicht kann ich einem ja auch helfen, da ich grad eine JTable erstellt habe, wo ich mit einem Dialog neue Datensätze hinzufügen kann, editieren oder löschen. 


Ich habe eine Methode wo das Model eines DefaultTableModels nochmals neu gerechnet und dem JTable übergeben wird. 

Vielleicht bringen dir die Methoden etwas:

tableUserModel=new DefaultTableModel(tableUsers,tableHeadline);
tableUserModel.fireTableDataChanged();
tableUserModel.fireTableStructureChanged();
userTable.setModel(tableUserModel);
userTable.repaint();
userTable.updateUI();

Eventuell sind da überflüssige Methoden dabei


----------



## André Uhres (11. Apr 2010)

Siehe auch die Artikel über Table Models im Java Tips Weblog


----------

