# JTable und Model



## Gast2 (17. Jun 2007)

Hallo,
ich habe die Methode


```
public boolean isCellEditable(int row, int column) {
 	if (column == 1) 
                {		
	 return true; 
                 }
                   return super.isCellEditable(row, column);
	}
```


überschrieben funktioniert auch wunderbar,dass nur die 2te spalte editierbar ist,aber wie lese ich den geänderten werd aus ????und sobald ich enter drücker bekommt die zelle ihren alte wert wieder...
tabelle.getValueat(); hat noch den alten wert


----------



## SebiB90 (17. Jun 2007)

du musst setValueAt() überschreiben.
der methode wird der neue wert übergeben. und wenn du da den wert nicht setzt, geht er verloren...


----------



## kleiner_held (17. Jun 2007)

Wo hast du diese Methode überschrieben? An der JTable oder an deinem TableModel? Richtig ist, sie am TableModel zu überschreiben. Außerdem muss wie schon gesagt die Methode setValueAt() des Models richtig implementiert sein und nach der (internen) Datenänderung ein passender TableModelEvent ausgelöst werden.


----------



## Gast2 (17. Jun 2007)

ja hab sie im tabelmodel überschrieben und des mit der setValue hab ich auch gemacht ,aber ich weiß nicht wie den wert überhaupt auslese!!!!!
Was wäre ein entsprechendes Event???


----------



## kleiner_held (17. Jun 2007)

Was für ein TableModel verwendest du denn? Komplett selbst geschrieben, von AbstractTableModel abgeleitet oder von DefaultTableModel abgeleitet?
Ich habe meistens ein Klasse von AbstractTableModel abgeleitet, beim Aufruf von setValueAt ändere ich intern den Wert der Zelle, je nachdem wo er gespeichert ist (in einer List in einem Array oder ähnlichem) und dannach rufe ich fireTableRowsUpdated(int firstRow, int lastRow) auf (die Methode wird von der Superklasse AbstractTableModel bereitgestellt). Den Rest macht die JTable dann schon von selbst.


----------



## Gast2 (17. Jun 2007)

ja kompeltt selbst geschrieben abstract....
ja schon des ist mir alles bewusst muss aber ich weiß nicht wie den geänderten wert aus der zelle raus bekomm!!!!!muss ich ein textfeld in diesem colum adden????


----------



## Gast2 (17. Jun 2007)

```
JTextfield value;


 tData= new MEDJTable(model,35,200,MEDSizeManager.gethauptPanelSize().width-40,400,"Parameter")
		 {
 			public boolean isCellEditable(int row, int column) {
 				if (column == 1) {
 				
		 		return true;
 				}
				return super.isCellEditable(row, column);
 			}
 		};


 tData.getColumnModel().getColumn(1).setCellEditor(
 	 		 	new DefaultCellEditor(value));

	public void actionPerformed(ActionEvent ae) {

		if(ae.getSource()==value)
		{
			model.setValue(value.getText(),tData.getSelectedRow(),1);
		}



/* MEIN MODEL*/


public class MEDJTabellenModel extends AbstractTableModel  {


public void setValue(Object value, int row, int col) 
	  {
		  super.setValueAt(value, row, col);
	    	  super.fireTableRowsUpdated(row,col);
	               //fireTableCellUpdated(row, col);
	   }
```


----------



## kleiner_held (17. Jun 2007)

kurze Ablaufbeschreibung:
Die JTable hat einen default TableCellEditor (ein JTextField), der wird gestartet wenn du in die Zelle-Doppelklickst. Der TableCellEditor bekommt beim Starten den aktuellen Wert der Zelle übergeben, wenn du ein dem Textfield dann Enter drückst, wird über einen kleinen Umweg (der für das Beispiel irrelevant ist) durch die JTable and dem TableModel die Methode setValueAt aufgerufen. Das wars erstmal für die JTable.
Das TableModel setzt intern den neuen Wert und ruft dann ein fireTableRowsUpdated(int, int) auf. Die JTable ist als TableModelListener registriert, bekommt den Event und ruft am TableModel wieder ein getValue() auf um die Anzeige zu aktualisieren. 

Du musst also im TableModel nicht aktiv die Zelle ändern sondern nur sicherstellen, das nach setValueAt ein fireTableRowsUpdated() aufgerufen wird und in Zukunft die Methode getValueAt den neuen Wert zurückgibt (indem du z.B.: vorher in setValueAt den Wert in einer internen Datenstruktur geändert hast.

Edit: Ok hab grad erst deinen Code gesehen. super.setValueAt(value, row, col);  in deinem TableModel kann nicht funktionieren, da die Methode in AbstractTableModel nicht implementiert ist. Poste doch mal dein ganzes TableModel oder ist es zu umfangreich?


----------



## André Uhres (17. Jun 2007)

Gibt es einen bestimmten Grund, daß du nicht von "DefaultTableModel" ableitest?
Das ist nämlich eine *funktionierende* Implementation und meistens braucht man dann 
weiter nichts zu überschreiben als "getColumnClass" und "isCellEditable" .


----------



## Gast2 (17. Jun 2007)

```
package studio.base;

import java.util.Vector;

import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;

public class MEDJTabellenModel extends AbstractTableModel  {

	Vector vData;
	Object[] oData;
	int col;
	String[]sColheads;
//	public MEDJTabellenModel(Vector data,String[] colheads)
//	{
//		super();
//		vData=data;
//		col=colheads.length;
//		sColheads=colheads;
//	}
	public MEDJTabellenModel(Object[] data,String[] colheads)
	{
		super();
		oData=data;
		col=colheads.length;
		sColheads=colheads;
		
	}
	public int getColumnCount() {
		// TODO Auto-generated method stub
		return sColheads.length;
	}
	
	   public String getColumnName(int columnIndex)
	   {
	     return sColheads[columnIndex].toString();
	   }
	

	public int getRowCount() {
		
		if(oData==null)
		{
			return 0;
		}
		return oData.length;
	}

	public Object getValueAt(int row, int col) {
		// TODO Auto-generated method stub
		Object[] vRow=null;
		vRow =(Object[])oData[row];
		return vRow[col].toString();
	}
	
	  public void setValue(String value, int row, int col) 
	  {
		  //oData[2] = value;
		  super.setValueAt(value, row, col);
		  super.fireTableRowsUpdated(row,col);
		  super.fireTableStructureChanged();
	       super.fireTableCellUpdated(row, col);
	   }
	  
//	  public void setData(Vector data)
//	  {
//		vData=data;
//		fireTableStructureChanged();
//	  }

	  public void setData(Object[] data)
	  {
		oData=data;
		fireTableStructureChanged();
	  }
	  public  String[] getcolheads()
	  {
		 return sColheads; 
	  }
	  

	  
}
```


----------



## kleiner_held (17. Jun 2007)

```
public void setValueAt(String value, int row, int col)
     {
         Object[] vRow=null;
         vRow =(Object[]) oData[row];
         vRow[col] = value; 
         super.fireTableCellUpdated(row, col);
      }
```

Ansonsten:
1. wenn du nur einen einfachen zweidimensionalen Array als Datenmodel verwendest, kannst du wie Andre schon sagte auch gleich ein DefaultTableModel überschreiben.
2. Bei dem Code in deinem 4ten Post brauchst du weder die JTable überschreiben noch einen überschriebenen DefaultCellEditor zu verwenden. Die Standardklassen reichen völlig.


----------



## Gast2 (17. Jun 2007)

ok thx ich versuchs mal...
ja ich nehm ein Object[] weil so meine datenbank auslese und so die tabellen leicht abbilden kann


----------



## Gast2 (17. Jun 2007)

ja ich nehm ein Object[] weil so meine datenbank auslese und so die tabellen leicht abbilden kann
ok hab die methode eingefügt in meinem model...
hab in meine dialog dass hier gemacht aber ohne erfolg 

```
value.addActionListener(this);

		tData.getColumnModel().getColumn(1).setCellEditor(
 	 		 	new DefaultCellEditor(value));


		if(ae.getSource()==value)
		{
			model.setValueAt(value.getText(),tData.getSelectedRow(),1);
		}
```


das war mein 2ter versuch des klappt nur einmal danach kann überschreibt er wieder alles ich verstehs halt nicht so richtig,warum es nicht klappt

```
public void actionPerformed(ActionEvent ae) {

		if(ae.getSource()==value)
		{
			Object[] row=(Object[]) vData[tData.getSelectedRow()];
			row[1]=value.getText();
			vData[tData.getSelectedRow()]=row;
			model.setData(vData);
			tData.setModel(model);
			
		}
```


----------



## Gast2 (18. Jun 2007)

ok sobald ich mit der mouse hineinklicke funktioniert es!!!!!! nur wenn ich mit der enter taste das feld befüll dann klappt es nicht


----------



## kleiner_held (18. Jun 2007)

Du brauchst keinen eigenen TableCellEditor und kein eigenes JTextField fuer das was du vorhast, verwende einfach die defaults der JTable und dein selbstgeschriebenes TableModel.

Wenn du einen DefaultCellEditor nimmst und mit einem eigenen JTextField fuetterst, bei dem du ins Event-Handling eingreifst, dann wird es sehr seltsame Effekte geben.


----------



## Guest (19. Jun 2007)

ok!!!
aber wann ruf ich dann die methode setValueAt.... auf?So hab ich sie in meinem actionperformed()von meinem Jtextfield


----------



## kleiner_held (19. Jun 2007)

Du rufst sie gar nicht auf.
Das macht die JTable selbststaendig, probiers doch einfach mal aus.


----------



## Gast2 (19. Jun 2007)

Nee leider nicht sobald ich enter drücke steht der alte wert drin


----------



## kleiner_held (19. Jun 2007)

Beispiel

```
public class EditableTableTest
{
	
	public static void main(String[] args)
	{
		String values[][] = new String[][] {{"eins", "eins"}, {"zwei", "zwei"}, {"drei", "drei"}, {"vier", "vier"}};
		String columns[] = new String[] {"read-only", "writable"};
		JTable table = new JTable(new DefaultTableModel(values, columns)
		{
			public boolean isCellEditable(int row, int column)
			{
				return column == 1;
			}
		});
		JFrame frame = new JFrame();
		frame.add(new JScrollPane(table));
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		frame.pack();
		frame.setVisible(true);
	}
}
```

Wie man sieht, war in dem Fall kein neuer TableCellEditor noetig. Mit genau so einem Beispiel kannst du z.B. auch dein TableModel testen. Wenn im Quellcode immer noch alte Artefakte von vergangenen Tests rumoxidieren, kommst du nie auf einen gruenen Zweig.


----------



## Gast2 (19. Jun 2007)

mein model erbt von AbstractTableModel....


----------



## kleiner_held (19. Jun 2007)

Das hat damit nichts zu tun - der Fehler liegt wahrscheinlich in deinem TableModel, aber wenn du gleichzeitig am TableModel, an der uerberschriebenen JTable und an einem eigenen TableCellEditor rumschraubst, wird das nie was.
Das Beispiel zeigt, dass du nur eine stinknormale JTable benoetigst und keinen eigenen TableCellEditor. Wenn das Editieren dann nicht richtig klappt, liegt in deinem TableModel ein Fehler vor, der sich durch Debugging oder Log-Ausgaben eigentlich leicht finden laesst.


----------



## Gast2 (19. Jun 2007)

ja ich hab den celleditor weggelassen!!!!
 und es hatte was mit dem model zu tun 
weil bei den beiden models verhalten sich die setValueAt methoden unterschiedelich,des wusste ich nicht....
des problem war ich hab in meiner setValueAt methode einen String mit gegeben anstatt ein Object des hat ihm nicht gepasst, darum kam der alte wert...Deshalb hab ich den quatsch mit dem CellEditior versucht
also ich hab es so gemacht und es funktioniert jetzt endlich 

danke für die ganzen ratschläge

```
public void setValueAt(Object value, int row, int col) 
  { 
      Object[] vRow=null; 
      vRow =(Object[]) oData[row]; 
      vRow[col] = value; 
      super.fireTableCellUpdated(row, col); 
   }
```


----------

