Swing JTextField Eventverarbeitung so richtig?

Status
Nicht offen für weitere Antworten.

-MacNuke-

Bekanntes Mitglied
Hiho.

Mal eine Frage. Ich will reagieren wenn Nutzer etwas in einem Textfeld eingegeben hat (ein mal neu durchrechnen oder was auch immer).

Und dachte ich an folgendes:
Ich hänge einen ActionListener und einen FocusListener an. Im ActionListener mache ich einen focusTraversal() und im FocusListener bei focusLost meinen Berechnungsaufruf. ActionListener alleine reicht nicht, da dieser die Tab-Taste und Feldwechsel per Maus ignoriert.

Quasi als Mini-Beispiel:
Code:
public class Main extends JFrame implements ActionListener, FocusListener {

    private JTextField feld;

    public Main() throws HeadlessException {
        feld = new JTextField();
        feld.addActionListener(this);
        feld.addFocusListener(this);
        this.add(feld,BorderLayout.NORTH);
        JButton btn = new JButton("Klick mich");
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                feld.setText("Hallo");
            }
        });
        this.add(btn,BorderLayout.SOUTH);
    }

    public static void main(String[] args) {
        Main m = new Main();
        m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        m.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        JTextField fld = (JTextField) e.getSource();
        fld.transferFocus();
    }

    public void focusGained(FocusEvent e) {
    }

    public void focusLost(FocusEvent e) {
        System.out.println("Focus lost - hier ansetzen");
    }
}

Problem ist jetzt noch, dass er auch anfangen würde zu berechnen, wenn man einfach nur durch die Felder "durchklickt" bzw. mit Tab durchgeht.

Ich weiß, dass man mit einem DocumentListener rausbekommt, wenn an einem Textfeld direkt etwas geändert wurde. Problem ist hier nur, dass dieser auch aufgerufen wird, wenn ich per setText die Felder aktualisiere (Datensatzwechsel z.B.).

Hier könnte man natürlich einen DocumentListener schreiben, wo man einen Status setzt, ob er Events ausführen soll oder nicht, um dann die Berechnung nur bei manueller Eingabe anzuschmeißen, aber das klingt für mich ein bisschen nach "dirty hack".

Gibt es da sonst noch einen "eleganten" Weg, dass zu machen?

Danke.
 
So ein Status-Flag ist eigentlich kein "dirty hack" - zumindest habe ich das nie so empfunden, und sehe das für den allgemeinen Fall als günstigste Lösung an. Ist ja ein "altbekanntes" Problem bei MVC:
Modell hat sich geändert -> View wird upgedated -> Model wird "geändert" -> ....
Das zweite "geändert" steht in Anführungszeichen, weil eine weitere Lösung dieses Problems darin besteht, dass das Modell Events konsequent NUR dann wirft, wenn die neuen Daten wirklich anders sind als die alten. Sollte man i.a. auch so machen, trotzdem kann man auch (ggf. sogar zusätzlich) ein Flag verwenden.

Auf Alternativlösungen wäre ich jetzt auch gespannt....
 
für mich ist es ein Dirty Hack für eine der zahllosen Lücken, die praktisch jedes Framework hat, ob Swing, JFreeChart, Hibernate oder wer auch immer,
es wurde mal wieder irgendein Feature nicht bedacht, es gibt weder Einstellungsmöglichkeiten noch Nachbesserungen durch Vererbung

hier ist es die Unterscheidung in User-Events (Maus, Tastatur) vs. Programm-Events,
für mich müsste das ein Parameter in jeder Art Event für Komponenten mit denen man direkt interagieren kann (auch Selektion in Tabellen usw) sein,
im Listener kann man dann per if/ else unterscheiden oder den Listener eh nur für User-Events registrieren usw.

das Problem kann man aus verschiedenen Richtungen sehen,
an anderen Stellen möchte ich für einige der setText()-Aufrufe vom Programm aus dieselben Aktionen ausführen wie vom User,
in dem Fall wäre es schöner, wenn es eine Möglichkeit gäbe, mal setText() mit Event-Auslösen und mal ohne auszuführen

jeder mag es anders, nur mit einem selbstgeschriebenen System kann man sowas am besten anpassen,
ein Status-Flag statt eines schönen Parameters im Event zählt da für mich klar als "dirty hack" 😉
 
Zuletzt bearbeitet von einem Moderator:
Hm. Ich glaube, diese Unterscheidung zwischen User- und Programm-Events wäre auch schwierig konsequent umzusetzen
Code:
ToogleButton wird auf "ON" geschaltet
-> User-Event wird geworfen
-> User-Event wird gefangen
    In ein TextField wird der String "ON" geschrieben
    -> Event wird geworfen - User-Event oder Programm-Event?
Das kann vermutlich beliebig kompliziert werden. Spontan würde ich sagen, dass es dann sogar sein KÖNNTE, dass man bei jeder Änderung seinen Ausweis vorzeigen müßte (um ggf. das "User-Flag" von übergeordneten Events "weiterreichen" zu können) - im Sinne von
Code:
public void actionPerformed(ActionEvent e)
{
    boolean thisActionIstCausedByUser = e.isUserEvent();
    textField.setText("ON", thisActionIstCausedByUser);
}
oder so ... also, ich glaube die Problematik an sich ist nicht vollkommen trivial. Ansätze wie "valueIsAdjusting" bei Slider usw. gehen ein bißchen in diese Richtung, decken aber nur sehr spezielle Fälle ab.
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben