# JTable listener



## thesa (23. Mai 2007)

Servus

Kann mir wer helfen folgendes Problem zu lösen?


```
table.getModel().addTableModelListener(new TableModelListener(){
            public void tableChanged(TableModelEvent arg0) {
                    Double b = (Double)table.getValueAt(1, 3);
                    table.setValueAt(b+1, 1, 4);
           }
});
```

Problem:
Endlos Schleife, da setValue auch gleich den Listener wieder auslöst. Kann mir wer sagen wie ich das Problem lösen kann? Hab was über selectionListener gefunden aber echt nicht kapiert wie ich das Ding benutzen sollte.

freundliche Grüsse
thesa


----------



## André Uhres (23. Mai 2007)

Du könntest den TableModelListener vor dem setValueAt ausschalten und danach wieder einschalten:

```
AbstractTableModel model = ((AbstractTableModel)table.getModel());
                TableModelListener tml = model.getTableModelListeners()[0];
                model.removeTableModelListener(tml);
                table.setValueAt(b+1, 1, 4);
                model.addTableModelListener(tml);
```


----------



## thesa (24. Mai 2007)

Jo an das habe ich auch schon gedacht, aber das ist ja etwa das selbe wie ein flag zu benutzen. Gibt es da noch eine sauberere Variante?


----------



## André Uhres (24. Mai 2007)

thesa hat gesagt.:
			
		

> ..Gibt es da noch eine sauberere Variante?


Naja, für solche Fälle ist die Methode "removeTableModelListener" doch wohl gedacht  :wink:


----------



## SlaterB (25. Mai 2007)

ansonsten wäre es eher eine Aufgabe für ein eigenes TableModel,
die eigene setValueAt()-Operation zu überwachen und dann gleichzeitig mehrere Werte zu ändern, 
da muss man vielleicht noch fireXYEvent() aufrufen

und auch in diesem Falle sollten alle Listener doch wohl davon informiert werden,
man hat ja nicht immer nur einen einzelnen Listener


----------



## thesa (26. Mai 2007)

hmm.. mein Problem ist noch nicht gelöst.

Die Version mit dem Listener ein und ausschalten will nicht wirklich funktionieren, da ich ja den setValue Befehl im tableChanged aufrufe.


```
//global:
private TableModelListener tml = new MyTableModelListener();

//inner Class:

    class MyTableModelListener implements TableModelListener{

        public void tableChanged(TableModelEvent arg0) {
            for (int i=0; i<table.getRowCount(); i++){
                Double d = (Double) table.getValueAt(i, 2);
                Double b = (Double)table.getValueAt(i, 3);
                table.getModel().removeTableModelListener(tml);
                table.setValueAt(b*d, i, 4);
                table.getModel().addTableModelListener(tml);
            }
            brutto.setText(Double.toString(summe));
            repaint();
            System.out.println("teeeest");
        }
    }

//Konstruktor:
table.getModel().addTableModelListener(tml);
```

Ziel: Sobald der User ein Wert in Spalte 2 oder 3 ändert soll der Wert in Spalte 4 neu berechnet werden.
Fehler: Feld in Spalte 4 bleibt leer, also der setValue wird nicht angezeigt. (die Tabelle wir jeweils neu gezeichnet)

Irgendwelche Tipps?


----------



## André Uhres (26. Mai 2007)

```
public void tableChanged(TableModelEvent arg0) {
            table.getModel().removeTableModelListener(tml);
            for (int i=0; i<table.getRowCount(); i++){
                Double d = (Double) table.getValueAt(i, 2);
                Double b = (Double)table.getValueAt(i, 3);
                table.setValueAt(b*d, i, 4);
            }
            table.getModel().addTableModelListener(tml);
            brutto.setText(Double.toString(summe));
            System.out.println("teeeest");
        }
```


----------



## thesa (26. Mai 2007)

Und wo sollte da ein Unterschied in der Funktion der Methode sein?
Der code ist vll weniger ugly aber mit meinem Problem, das in der Tabelle nichts angezeigt wird hat das ja nichts zu tun oder?


----------



## kleiner_held (26. Mai 2007)

SlaterB hat gesagt.:
			
		

> ansonsten wäre es eher eine Aufgabe für ein eigenes TableModel,
> die eigene setValueAt()-Operation zu überwachen und dann gleichzeitig mehrere Werte zu ändern,
> da muss man vielleicht noch fireXYEvent() aufrufen


Genau so würde ich es machen. Getriggerte Datenänderungen in einen TableModelListener zu packen ist mMn ein Designfehler und alle Workarounds ala Listener an- und abschalten bzw Listener deregistrieren und erneut registrieren sind nur Krücken.


----------



## thesa (26. Mai 2007)

Ja das mit dem add und remove listener sehe ich genau so. Trotzdem hat bei mir die Lauffähigkeit momentan höchste Priorität. (Zeitdruck)

Das Problem mit dem eigenen TableModel ist, das ich schon ein solches benutze, welches aber für x andere Tabellen auch noch benutzt wird. Zudem verstehe ich nicht genau wie ich dort eine setValue Operation überwachen kann.

Ist es zu viel verlangt wenn ich um ein Beispiel bitte? (oder super link für genau dieses Problem)

freundliche Grüsse
thesa


----------



## kleiner_held (26. Mai 2007)

kannst Du nicht einfach ein neues Model bauen, welches vom Allgemeinen erbt?

```
public class MySpecialTableModel extends MyGenericTableModel
{
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) 
  {
     // I. Änderung weiterleiten
     super.setValueAt(value, rowIndex, columnIndex);
     // II. eigene Ändrung nachschieben
     if (columnIndex == 2 || columnIndex == 3) 
     {
        Double spalte2 = (Double) getValueAt(rowIndex, 2);
        Double spalte3 = (Double) getValueAt(rowIndex, 3);
        super.setValueAt(spalte2 * spalte3, rowIndex , 4);
     }
  }
}
```


----------



## thesa (26. Mai 2007)

hrhr.. gut Idee. 
Hab das ganze mal implementiert und der setValueAt Befehl vom neuen Model wird auch ordnungsgemäss ausgeführt und weitergeleitet. Hab zwar noch ein Problem mit dem Wert setzen aber das werd ich schon noch hinbekommen. 

Danke für die Hilfe.


----------



## André Uhres (27. Mai 2007)

thesa hat gesagt.:
			
		

> Und wo sollte da ein Unterschied in der Funktion der Methode sein?..


Der Unterschied: es funktioniert


----------

