Ergebnis des Listeners ermitteln

Status
Nicht offen für weitere Antworten.

daNny

Aktives Mitglied
Hallo Leute!

Ich habe da gerade ein Problem, wo ich es glaube ich total verpeile.

Ich habe mir einen Dialog gebaut, in dem sich eine Tabelle, gefüllt mir Werten, befindet. Jetzt wollte ich erreichen, dass wenn man auf die Spalten des JTableHeader klickt, die ID der Spalte in eine Liste einfügt wird, wenn sie noch nicht drin ist. Falls sie sich schon in der Liste befindet, dann soll sie wieder entfern werden.
Damit will ich erreichen, dass man per Knopfklick nur diese Spalten auslesen kann und diese dann weiterverarbeitet.

Gelöst habe ich das nach einigem Nachlesen nun so:

Code des DIalogs:
Code:
DefaultTableModel tMod = new DefaultTableModel(0, reader.getColumnCount());
this.jTable1.setModel(tMod);
for (String[] s : data) {
    tMod.addRow(s);
}
JTableHeader header = this.jTable1.getTableHeader();
header.addMouseListener(new ColumnHeaderListener());
Ich erstelle also ein neues TableModel und update somit die als Attribut definierte Tabelle. in der Schleife wird diese dann mit den Daten, die ich aus dem Reader bekomme, befüllt.
Danach füge ich dem Header der Tabelle dann einen Listener hinzu, der so aussieht:

Code:
public class ColumnHeaderListener extends MouseAdapter {
    
    @Override
    public void mouseClicked(MouseEvent evt) {
        
        JTable table = ((JTableHeader)evt.getSource()).getTable();
        TableColumnModel colModel = table.getColumnModel();
    
        // Index der angeklickten Spalte
        int spaltenIndex = colModel.getColumnIndexAtX(evt.getX());
        
     }
}
Jetzt fehlt es mir allerdings gerade an der zündenden Idee, wie ich die nun ermittelte ID in den DIalog zurückbekomme, sodass ich diese in eine Liste einfügen bzw. falls schon vorhanden auch wieder löschen kann. Könnte mir da jemand auf die Sprünge helfen?
 
naja, du brauchst eine Funktion, die den Wert in die Liste einfügt. Diese musst du dann mit dem Ergebnis deiner getColumIndexAt- Funktion aufrufen.
 
1 Möglichkeit: JTable ableiten und die Liste hier als als Attribut aufnehmen. Statt JTable die Ableitung im Listener verarbeiten.
 
Danke schonmal für deine Antwort.

Dass ich das mit ner Funktion bzw. Methode in ne Liste einfügen/entfernen kann ist mir schon klar. Aber wie komme ich in dem Listener an den Dialog, in dem sich der Header befindet? Ich hatte das mal mit mehreren getParent() aufrufen hintereinander versucht. Die Source steht ja in dem Event drin. Aber irgendwie hatte ich immer nen Casting-Problem.
Das ganze müsste doch bestimmt auch eleganter zu lösen sein.

Also im Dialog könnte ich ja ne öffentliche Methode einfügen, wie:
Code:
public void addColumn(Integer i) {
    if (list.contains(i)) {
        list.remove(i);
    } else {
        list.add(i);
   }
}

Nur irgendwie müsste ich ja auch an die Methode drankommen aus dem Listener heraus 😉
 
@ HLX: Das klingt schonmal interessant.

Du meinst quasi, dass ich eine Art TabelleMitListe-Klasse erstelle, die aus JTable abgeleitet ist und zusätzlich eine Liste beinhaltet, die meine selektierten Spalten beinhaltet?

ALso so ungefähr?
Code:
public class TableMitListe extends JTable {
    private List<Integer> list;
    
    public TableMitListe() {
        super();
        this.list = new LinkedList<Integer>();
    }
    
    /**
     * Fügt eine SPalte in die interne Liste ein oder löscht sie, falls sie
     * schon existiert
     * @param i Index der Spalte
     */
    public void addColumn(Integer i) {
        if (list.contains(i)) {
            list.remove(i);
        } else {
            list.add(i);
       }
    }
}

Ich denke, da sollte ich mich mal hinterklemmen
 
Die Idee funktioniert bisher sehr gut! Jetzt bin ich allerdings auf einen Fehler gestoßen, den ich absolut nicht nachvollziehen kann! Die Klasse sieht nun so aus:
Code:
public class SelectableColumnTable extends JTable {
    
    /** Die vom Benutzer ausgewählten Spalten */
    private List<Integer> columnSelection;
    
    /**
     * Erstellt eine neue SelectableColumnTable
     */
    public SelectableColumnTable() {
        super();
        this.columnSelection = new LinkedList<Integer>();
    }
    
    
    /**
     * Fügt den Index einer Spalte in die interne Liste ein
     * Falls sich ser Index der Spalte bereits in der internen Liste befindet,
     * so wird er aus dieser wieder entfernt.
     * @param i Index der Spalte
     */
    public void addToColummSelection(Integer i) {
        if (this.columnSelection.contains(i)) {
            this.columnSelection.remove(i);
        } else {
            this.columnSelection.add(i);
        }
    }
    
    @Override
    public void setModel(TableModel dataModel) {
        super.setModel(dataModel);
        this.columnSelection.clear(); 
    }
    
    public int getColumnSelectionCount() {
        return this.columnSelection.size();
    }
    
    /**
     * Leert die interne Liste der ausgewählten Spalten
     */
    public void clearColumnSelection() {
        this.columnSelection.clear();
    }

}

Wenn ich die setModel()-Methode auskommentiere, funktioniert alles suppi! Allerdings will ich diese überschreiben. Denn wenn ich ein neues Model einfüge, die Tabelle also einen neuen Inhalt bekommt, möchte ich, dass die ausgewählten Spalten geleert werden.

Allerdings hagelt es immer ne NullPointerException, und ich weiß nicht, wieso das so ist:
Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at de.hitseller.comparator.gui.SelectableColumnTable.setModel(SelectableColumnTable.java:49)
        at javax.swing.JTable.<init>(JTable.java:611)
        at javax.swing.JTable.<init>(JTable.java:539)
        at de.hitseller.comparator.gui.SelectableColumnTable.<init>(SelectableColumnTable.java:28)
Allerdings rufe ich die Methode nie mit einer Null-Referenz auf! Kann sich das jemand erklären?

Aber auf jeden Fall schonmal: Vielen Dank 😉
 
In deinem Konstruktor rufst du korrekterweise zuerst den Konstruktor von JTable auf. Dummerweise ruft der JTable-Konstruktor die Methode 'setModel' auf. Dabei wird deine Implementierung dieser Methode aufgerufen. Zum Zeitpunkt dieses Aufrufs ist deine LinkedList jedoch noch nicht initialisiert - das machst du ja erst später in deinem eigenen Konstruktor.
 
Wow! Super vielen Dank für die Hilfe 😉

Code:
@Override
    public void setModel(TableModel dataModel) {
        super.setModel(dataModel);
        if (this.columnSelection != null) {
            this.columnSelection.clear();
        }
    }
Tut's nun 😉
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben