JTable mit JComboBox und Listener, wie funktionieren sie?

HaGs

Grünschnabel
Hallo zusammen,

ich habe eine JTable, und für eine Spalte eine JComboBox definiert. Auf die Table habe ich einen MouseListener gelegt, um festzustellen, welche Reihe gerade ausgewählt ist (die Variable aktRow_ wird gesetzt), und auch für mein Popup Menü. Auf die CBox habe ich einen ItemListener gelegt, um auf Änderungen zu reagieren.

Vom Standpunkt eines Progi-Anwenders sollte es so sein:
Ich klicke in die CBox, wähle einen neuen Wert aus. Wenn sich die CBox schliesst dann sollte der ItemListener() reagieren. Dort wird dann ein TimerTask gestartet.

Momentan ist es aber so:
1.) Ich klicke in die CBox in einer Tabellezeile. Der ItemListener() wird aufgerufen und dann die getTableCellEditorComponent() Methode (hier wird meine Variable aktRow_ aktualisiert). Ich wähle einen neuen Wert aus, und der ItemListener() wird schon wieder aufgerufen.

2.) Ich wähle jetzt eine CBox einer anderen Zeile. Der ItemListener() wird aufgerufen. Nun hat meine Variable aktRow_ aber den Wert von vorhin (siehe 1. ), und nicht den Wert der gewählten CBox. Die getTableCellEditorComponent() Methode wird aufgerufen und erst jetzt ist meine aktRow_ wieder richtig, doch jetzt ist es zu spät.

Irgendwie ist hier das Verhalten der Listener in einer Tabelle mit CBox merkwürdig. Meine variable aktRow_ hinkt immer einen Schritt hinterher und ist nie aktuell, ausser man klickt zuerst in eine andere Tabellenzelle und dann in die CBox. Dann ist alles OK, weil ja der MouseListener durchlaufen wird (hier wird auch die variable aktRow_ aktualisiert).
Nur das entspricht nicht einer userfriendly Bedienung.

Ich brauche im ItemListener() die aktuelle Reihe der angewählten CBox, aber wie kann ich das realiseren? Hat jemand interesse mein i mal zu Testen, dann kann man den Effekt besser nachvollziehen.
 
Heyho,

habe in der Richtung noch nie etwas gemacht.... aber versuche es doch mal mit einem ChangeListener statt einem ItemListener :)
Oder du überlegst dir eine sinnige / gute if-Abfrage, die du in deine Listener schreibst...

Zum zweiten, versuchs mal mit getSelectedRow() damit arbeite ich zu 90% :)
Liefert einen Int zurück.

Hoffe, du kannst damit etwas anfangen!
Viel Glück!

edit:
JComboBox Example 1
JComboBox Example 2
 
Zuletzt bearbeitet:
Hallo,

eigentlich brauchst Du in dem Fall nur einen ActionListener an Deine ComboBox anzuhängen. Hier ein kleines Beispiel:
Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * The Class ComboBoxTest.
 */
public class ComboBoxTest extends JFrame {

    /**
     * Create a new instance of <code>ComboBoxTest</code>.
     */
    public ComboBoxTest() {
        super("ComboBoxTest");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        
        final JComboBox comboBox = new JComboBox(new String[] {"Hund", "Katze", "Maus"});
        final JPanel panel = new JPanel();
        panel.add(comboBox);
        getContentPane().add(panel, BorderLayout.NORTH);
        final JTextArea textArea = new JTextArea();
        getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
        comboBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final Object selectedItem = comboBox.getSelectedItem();
				textArea.append("ActionListener --> selectedItem: " + selectedItem + "\n");
			}
        });
    }

    /**
     * The main method.
     *
     * @param args the arguments
     */
    public static void main(String[] args) {
        final JFrame frame = new ComboBoxTest();
        final Dimension frameSize = new Dimension(600, 400);
        frame.setSize(frameSize);
        final Dimension screenSize =
            Toolkit.getDefaultToolkit().getScreenSize();
        final int frameX = (screenSize.width - frameSize.width) / 2;
        final int frameY = (screenSize.height - frameSize.height) / 2;
        frame.setLocation(frameX, frameY);
        frame.setVisible(true);
    }    
}

Grüße
Vincent
 
ich habe immer auch immer mit einem ActionListener gearbeitet und dann in diesem geprüft, ob die table.getSelectedRow() != -1 ist. So jedenfalls wurde der code nur dann aufgerufen, wenn in der combobox ein Wert ausgewählt wurde.
 
Heyho,

war das denn nicht auch dein Ziel?
wenn ja, sollte es ja nun klappen... sonst schau dir Vincents Beispel oder die aus meinem Post mal genau an :)

Grüße
 
Hallo an Alle,

bin erst jetzt nach Hause gekommen und habe Eure Vorschläge gelesen.
Zu Wyatt:
Aha, ChangeListener, muss ich ausprobieren.

Zu Vincentius und Inkog:
Den ActionListener hatte ich auch schon an der CBox hängen. Nur dort kann ich ja nicht die Tabellenzeile der CBox abrufen ( mit tabelle_.rowAtPoint(new Point(x_,y_)) ).
Ob es mit getSelectedRow() funktioniert muss ich erst Testen, könnte aber der Schlüssel zur Lösung sein.

Vorerst mal vielen Dank, jetzt habe ich wieder eine Richtung in der ich weiter machen kann. War schon am verzweifeln.:)
 
So habe diverses getestet:

1.) einen ChangeListener kann ich nicht an eine CBox adden. Die Methode (combo.addChangeListener) wird nicht angeboten.

2.) Im itemChangeListener rufe ich die getSelectedRow() Methode auf, bringt mir aber nicht die Zeile in der die CBox angeklickt wurde. Es scheint so, dass beim Klicken auf die TabellenCBox die Tabelle gar nicht mitbekommt in welcher Zeile die CBox liegt?!

3.) Es funktioniert nur mit einem Hilfszähler, der sich 2x hochzählt. Mit einer Zusatzabfrage kann dann die gewünschte Aktion gestartet werden. So wie es sein sollte. Dabei kann sowohl der itemChangeListener als auch der actionListener auf die CBox gehängt werden.

Hier jetzt mein funktionierende Endlösung, als Auszug:
:):)

Code:
class ComboListener_ implements ActionListener {
  int x=1; //Zähler
  public void actionPerformed(ActionEvent e_) {
    x++; // Zähler um eins erhöhen
    if(tabelle_.getSelectedRow()!=-1 && x>2) { //wenn eineZeile ausgewählt und der Zähler >2 ist
      fireEditingStopped(); //ist unbedingt notwendig, weil sonst der Wert der CBox nicht übernommen wird
      //Hier kann jetzt die Aktion stehen, die genau 1x ausgeführt wird
      x=1;
    }
  }//Methode Ende
}//Class Ende

Danke an Alle die mir geholfen haben, und schönen Abend.
 
Zurück