# Index von verschobenen Spalten (JTable)



## Miss Evil (12. Sep 2003)

Hallo, 

ich bräuchte nochmal eure Hilfe.
Ich habe ja ein Applet mit einer JTable. Ich kann die Zeilen neu sortieren, bekomme aber trotzdem über das TableModel die richtige Zeile geliefert. Wunderbar!
Allerdings kann ich im Applet mit der Maus die Spalten neu anordnen, bekomme da aber leider nur den Wert der sichtbaren Tabelle zurückgeliefert, wenn ich irgendwo drücke. 

Ich habe einen Vektor mit den Spaltentypen (columnTypes) Und im Moment frage ich eben:


```
if(columnTypes.elementAt(column).equals(COLUMN_TYPE_NORMAL_LINK) [...]
```

Das klappt natürlich nur, wenn die Tabelle ihren ursprünglichen Aufbau hat, da sich der Vector mit den Typen ja nicht neu sortiert, wenn ich das Applet ändere.

Hat jemand eine Idee, wie ich dieses Problem lösen kann? 

Danke


----------



## DTR (12. Sep 2003)

Du könntest versuchen die Informationen aus columnTypes direckt in die Spalten mit einzubauen. Also von TabelColumn ableiten, und ein zusätzliches Attribut mit anlegen für den Typ. Wenn du jetzt die Spalten umsortierst, werden die Informationen automatisch mit sortiert. Sie stecken ja in der Spalte mit drin.


----------



## mariopetr (12. Sep 2003)

im tablehaeder nach dem namen der spalte suchen, daraus ergibt sich der index der entsprechenden spalte.


----------



## Guest (15. Sep 2003)

DTR hat gesagt.:
			
		

> Du könntest versuchen die Informationen aus columnTypes direckt in die Spalten mit einzubauen. Also von TabelColumn ableiten, und ein zusätzliches Attribut mit anlegen für den Typ. Wenn du jetzt die Spalten umsortierst, werden die Informationen automatisch mit sortiert. Sie stecken ja in der Spalte mit drin.



Die Idee finde ich ja schon gut, allerdings habe ich dann das Problem, dass er meine Renderer nicht mehr anspricht. 

```
table.setDefaultRenderer(Object.class, new TableCellRenderer());
		tcm = table.getColumnModel();
		// renderer for header
		table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer(chl, button_up, button_down));
		// searching for possible column types
		for (int i=0; i<columnTypes.size(); i++) {
			try{
				MTableColumn column = (MTableColumn)tcm.getColumn(i);
				column.setPreferredWidth(Integer.parseInt((String)columnWidths.get(i)));
				if (COLUMN_TYPE_NORMAL.equals(columnTypes.elementAt(i))){
					column.setType((String)columnTypes.elementAt(i));
				}else if(COLUMN_TYPE_NORMAL_LINK.equals(columnTypes.elementAt(i))){
					column.setType((String)columnTypes.elementAt(i));
				}else if(COLUMN_TYPE_HIGHLIGHT.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new HighlightCellRenderer());
					column.setType((String)columnTypes.elementAt(i));
```

Vorher hatte ich den gleichen Code eben nur mit TableColumn und ohne setType():

Was hab ich da falsch gemacht?

Ach ja, die Klasse MTableColumn enthält zurzeit nur einen Konstruktor und die get-/set-Methoden.

```
public MTableColumn (int index){
		super(index);
		type = "";
	}
```


----------



## DTR (15. Sep 2003)

Hat es einen Grund, warum du nicht direkt an der TabelColumn die Renderer setzt?


----------



## Guest (15. Sep 2003)

Direkt an TableColumn? Sorry, die Frage verstehe ich jetzt nicht ganz 
Aber das ist nur ein Ausschnitt meines Codes, ich habe danach nochmal ca. 8 mal diese If_abfrage, da ich immer unterschiedliche Renderer habe... 
War das in etwa die Info, die du haben wolltest? Hier mal der komplette Block im laufenden Original.

```
for (int i=0; i<columnTypes.size(); i++) {
			try{
				TableColumn column = tcm.getColumn(i);
				column.setPreferredWidth(Integer.parseInt((String)columnWidths.get(i)));
				if (COLUMN_TYPE_NORMAL.equals(columnTypes.elementAt(i))){
				}else if(COLUMN_TYPE_NORMAL_LINK.equals(columnTypes.elementAt(i))){
				}else if(COLUMN_TYPE_HIGHLIGHT.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new HighlightCellRenderer());
				} else if (COLUMN_TYPE_HIGHLIGHT_LINK.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new HighlightCellRenderer());
				} else if (COLUMN_TYPE_NUMBER.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new NumberCellRenderer());
				} else if (COLUMN_TYPE_NUMBER_LINK.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new NumberCellRenderer());
				} else if (COLUMN_TYPE_NUMBER_COLOR.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new ColoredNumberCellRenderer());
				} else if (COLUMN_TYPE_NUMBER_COLOR_LINK.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new ColoredNumberCellRenderer());
				} else if (COLUMN_TYPE_INDICATOR_NORMAL.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new NumberCellRenderer());
				} else if (COLUMN_TYPE_INDICATOR_NORMAL_LINK.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new NumberCellRenderer());
				} else if (COLUMN_TYPE_INDICATOR_COLOR.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new ColoredNumberCellRenderer());
				} else if (COLUMN_TYPE_INDICATOR_COLOR_LINK.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new ColoredNumberCellRenderer());
				} else if (COLUMN_TYPE_ICON.equals(columnTypes.elementAt(i))) {
					column.setCellRenderer(new IconCellRenderer());
				}
			}
			catch (Exception e){
				System.out.println(e.getMessage());
			}
```


----------



## DTR (15. Sep 2003)

Ja, das ist das was ich haben wollte. Kannst du dann bitte nochmel dein Problem genauer beschreiben.


----------



## Guest (15. Sep 2003)

Mein Problem ist, dass, wenn ich die TableColumn in eine MTableColumn casten will (siehe Code 1) dann werden die Renderer und die Verlinkung nicht mehr aktiviert. Außerdem bekomme ich später auch eine ClassCastException, wenn ich beim MouseListener die Spalte haben möchte.

```
col = table.columnAtPoint(event.getPoint());
				column = (MTableColumn)tcm.getColumn(col);
```

Ich muss danach dann nämlich an das Extraattribut, welches ich hinzugefügt habe.


----------



## DTR (15. Sep 2003)

Poste doch mal die Klasse MTableColumn.


----------



## Guest (15. Sep 2003)

```
public class MTableColumn extends TableColumn {
	private String type;
	
	public MTableColumn (int index){
		super(index);
		type = "";
	}

	/**
	 * @return
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param string
	 */
	public void setType(String string) {
		type = string;
	}
	
}
```

Da ist nicht viel drin, da ich das meiste an die Superklasse deligiere...


----------



## DTR (15. Sep 2003)

Tut mir leid, aber ich finde im Moment auch nicht das Problem.


----------



## Miss Evil (15. Sep 2003)

Trotzdem danke für deine Hilfe 

Ich habe jetzt auch einen anderen Weg gefunden... zwar nicht so schön, aber funktioniert... Ich habe jetzt mit modelindex gearbeitet.


----------



## Miss Evil (16. Sep 2003)

So, eine letzte Frage, bevor ich mit meinem Applet fertig bin *bg*

Ich habe ja meine JTable und kann diese in unefähr 18 verschiedenen Arten sortieren. Jetzt brauche ich allersings, wenn es irgendwie machbar ist, den Index der geklickten Reihe... 
Ich weiß, dass ich über das DefaultTableModel die Werte bekomme, aber nicht den Index. Also im Prinzip das gleiche Problem, wie gestern, nur diesmal auf den Zeilen. 

Also, die Werte bekomme ich über: 

```
for(int i=0; i<desiredColumnsVector.size(); i++){
					for(int j=0; j<symbolCount; j++){
						if(((Vector)dtm.getDataVector().elementAt(row)).elementAt(i).equals(symbols.elementAt(j))){
								symbol = (String)symbols.elementAt(j);
								linkCells(column, symbol);
						}
					}
				}
```

Aber ich bräuchte den index und dazu habe ich noch nichts gefunden. 

Das wars dann aber auch mit meinem Applet und die nächsten Fragen drehen sich (voraussichtlich) mal um was anderes *g*

Danke


----------



## DTR (16. Sep 2003)

Hi,

funktioniert getSelectetRow() nicht?


----------



## Miss Evil (16. Sep 2003)

Doch, aber dann habe ich nur den Wert der Reihe in der View und nicht im Model. Da ich aber wieder intern was vergleichen muss,  ist die aktuelle Position in der View völlig uninteressant.


----------



## DTR (16. Sep 2003)

Warum stimmen die Indices in Model und View nicht überein?


----------



## Miss Evil (16. Sep 2003)

weil ich die View umsortieren kann. Ich kann jede Spalte auf-/absteigend sortieren. Das macht 18 verschiedene Möglichkeiten, wo die Zeilen stehen können. Und da sich die Werte ja beim Update ja auch verändern, sind sie nie in der Zeile, wie das Model sie am Anfang eingeordnet hatte. 
Über DefaultTableModel.getElementAt(index) (bzw. setElementAt) kann man auf die Zelle im Model zugreifen (siehe Codebeispiel bei der Frage) allerdings nur auf den Wert und der nützt mir nichts.


----------



## DTR (16. Sep 2003)

Wie sortierst du denn die Zeilen ohne das Model zu ändern?


----------



## Miss Evil (16. Sep 2003)

Hab ich da was falsch verstanden? 
Ich dachte, wenn ich durch Mausklick im Applet was ändere, ändere ich nur die View und das Model bleibt so, wie es am Anfang angelegt wurde.  Ich klicke einfach auf die spaltenüberschriften, um auf-/absteigend zu sortieren....

Zitat aus Handbuch der Java Programmierung (http://www.rz.fhtw-berlin.de/hjp3/k100242.html#ixa102692)


Bei der Verwendung der Methoden getValueAt und setValueAt ist es wichtig zu wissen, daß die angegebenen Zeilen- und Spaltenwerte sich auf die aktuelle Ansicht der Tabelle beziehen, nicht auf ihr Modell. Hat der Anwender beispielsweise die Spalten eins und zwei vertauscht, würde ein Zugriff auf ein Element in Spalte eins den Modellwert in Spalte zwei verändern und umgekehrt. Während dieses Verhalten erwartungskonform ist, wenn der Wert durch den Anwender editiert wird, würde es bei programmgesteuertem Aufruf zu einem logischen Fehler kommen, denn das Programm hat natürlich zunächst einmal keine Kenntnis davon, daß der Anwender die Spaltenreihenfolge verändert hat. In aller Regel werden programmgesteuerte Zugriffe auf einzelne Zellen daher nicht mit getValueAt und setValueAt ausgeführt, sondern an die gleichnamigen Methoden des TableModel delegiert.


----------



## DTR (17. Sep 2003)

Da man durch einfaches anklicken des Headers sortieren kann, ist neu für mich. Man kann halt immer noch etwas lernen. Ich hab das auch mal kurz ausprobiert und bei mir geht das garnicht (JDK 1.3). Deshalb würde ich wenn ich die Spalten tauschen wollte das mit der Maus machen, und wenn ich die Zeilen tauschen wollte, würde ich das Modell umsortieren. Dadurch stimmen dann, zumindest was die Zeilen betrifft, Model und View überein. 
Das löst aber dein Problem nicht. Ich werde nochmal überlegen, ob mir noch ein Weg einfällt dir zu helfen.


----------

