# Dynamisches Zuweisen von Daten an eine JTable zur Laufzeit



## Clip (28. Okt 2005)

Hallo,

ich habe eine Tabelle vom Typ jTable. Die Tabelle benutzt ein eigenes TableModel.

```
TableSorter sorter = new TableSorter(new MyTableModel());
jTTable = new JTable(sorter) {
```
(Das TableModel kommt aus einem Tutorial im Netz)

```
import java.util.Date;

import javax.swing.table.AbstractTableModel;

	public class MyTableModel extends AbstractTableModel {

	
		String[] columnNames = {"First Name",
	            "Last Name",
	            "Day of birth", 
	            "Sport",
	            "# of Years",
	            "Vegetarian"};

		Object[][] data = {
			{"Mary", "Campione", new Date(System.currentTimeMillis()) ,"Snowboarding", new Integer(5), new Boolean(false)},
			{"Alison", "Huml", new Date(System.currentTimeMillis()) ,"Rowing", new Integer(3), new Boolean(true)},
			{"Kathy", "Walrath", new Date(System.currentTimeMillis()) ,"Knitting", new Integer(2), new Boolean(false)},
			{"Sharon", "Zakhour", new Date(System.currentTimeMillis()) ,"Speed reading", new Integer(20), new Boolean(true)},
			{"Philip", "Milne", new Date(System.currentTimeMillis()) ,"Pool", new Integer(10), new Boolean(false)}
		};
		
	    public int getColumnCount() {
	    	return columnNames.length;
	    }

	    public int getRowCount() {
	        return data.length;
	    }

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

	    public Object getValueAt(int row, int col) {
	    	return data[row][col];	    	    		    
	    	}
	    
	    
	    
	    public Class getColumnClass(int c) {
	        return getValueAt(0, c).getClass();
	    }
	    
	    
	     // Don't need to implement this method unless your table's
	     // editable.
	     
	    public boolean isCellEditable(int row, int col) {
	        //Note that the data/cell address is constant,
	        //no matter where the cell appears onscreen.
	        if (col < 3) {
	            return false;
	        } else {
	            return true;
	        }
	    }

	    
	     // Don't need to implement this method unless your table's
	     // data can change.

	    public void setValueAt(Object value, int row, int col) {    		   
	        data[row][col] = value;         	    
	        fireTableCellUpdated(row, col);
	    }

	    public String[] getColumnNames() {
			return columnNames;
		}

	    public void setColumnNames(String[] columnNames) {
			this.columnNames = columnNames;
			fireTableDataChanged();
		}

	    public Object[][] getData() {
			return data;
		}

	    public void setData(Object[][] data) {
			this.data = data;
			fireTableDataChanged();
		}
	    	    
	}
```

Der TableSorter kommt hier her:
java.sun.com/docs/books/tutorial/uiswing/components/example-1dot4/TableSorter.java

Das Funzt soweit ganz gut.

Nun will ich aber nicht immer (eigentlich nie) feste Daten in der Tabelle haben. Ich stelle Daten aus der DB da. Zur Laufzeit werden diese Daten geupdated. D.h. die Tabelle muss zur Laufzeit mit neuen Daten versehen werden können. Ich hatte mal eine Version Programmiert, in der ich data und columnNames mit einer Set Methode zuweisen konnte.  Anschließend habe ich die Tabelle einfach neu instantiiert. Leider hat das nicht gefunzt (hat nur relativ lange Pausen gegeben und dann sah die Tabelle aus wie zuvor  ). 
Ich habe mich schon durch die Hilfe geschlagen, konnte aber kein Beispiel für die Lösung meines Problem finden.

Kurz: Wie implementiere ich am besten eine Methode, die es mir erlaubt zur Laufzweit die Daten der Tabelle möglichst performant zu ändern?

Danke!


----------



## Sky (28. Okt 2005)

In deinem Modell sollten die Daten in einer List oder in einer Collection sein; das ist besser als ein Array, wenn es sich ändern soll/muss.

Zusätzlich brauchst Du eine Methode zum hinzufügen der Daten, welche deinen Datencontainer erweitert und ein Event abfeuert.


----------



## Clip (31. Okt 2005)

Danke für den Tip!

Ich habe jetzt eine Methode implementiert, welche ein ResultSet in einer JTable darstellt:

```
public void drawResultSet(ResultSet data) throws SQLException {
		
		int columns = data.getMetaData().getColumnCount();
		
		for (int i = 1; i <= columns; i++){
			Vector vector = new Vector(15);		// 15 ist ein (dummer) Defaultwert. ToDo: verbessern!
			while (data.next()){
				vector.add(data.getObject(i));
			}					
			model.addColumn(data.getMetaData().getColumnName(i), vector);			
			data.first();									
		}			
	}
```

Das funktioniert auch. Leider geht auf diese Art mein TableCellRenderer Hops. Bzw. er denkt bei allen Daten würde es sich um Strings handeln. Ich kann anhand der Tabellenspaltennamen erkennen um was für Datentypen es sich handelt. Nur weiß ich nicht wie ich das der Tabelle mitteilen kann. Ich möchte natürlich Boolean, int und Date unterschiedlich dargestellt kriegen   (Diese Boolean CheckBox in einer Tabelle finde ich einfach Sexy ) 

Edit:
Und ausserdem funzt der TableSorter sonst auch nur für String, was relativ dämliche Date, Integer etc. Sortierung bedeutet....


----------



## AlArenal (31. Okt 2005)

Du musst in deinem Model getColumnClass(int index) anpassen. Wenn du weißt in welcher Spalte welche Daten stecken, sollte dich das nicht vor unlösbare Probleme stellen.


----------



## Clip (31. Okt 2005)

Danke!

fürs Archiv, das geht so (mit TableSorter s.o.):

```
private DefaultTableModel model = new DefaultTableModel();
	TableSorter sorter = new TableSorter(model){
		@Override
		public Class getColumnClass(int column) {
			Class myClass = extractClassFromHeader(column);					
			if (myClass != null) return myClass;
			else return super.getColumnClass(column);
		}
	};
```

wobei extractClassFromHeader(int)  eine Methode ist, zurückgibt um was für einen Typ es sich in einer Spalte handelt. Da  das bei jedem anders ist, mach es keinen Sinn die hier zu posten.


----------

