Swing: Gibt es eine Möglichkeit zwischen einem vom Benutzer verursacht ItemEvent und anwendungs ​​verursacht eine unterscheiden?

StackOverflow https://stackoverflow.com/questions/176150

Frage

Ich arbeite mit einer Combobox in einer Swing-basierte Anwendung, und ich bin eine harte Zeit, herauszufinden, was zwischen einem ItemEvent zu unterscheiden zu tun, das gegen einen von einem Benutzerereignis erzeugt wird, durch die Anwendung verursacht.

Zum Beispiel Lassen Sie uns sagen ich eine Combobox haben, ‚combo‘ und ich bin für itemStateChanged Ereignisse mit meinem ItemListener hören, ‚listener‘. Wenn entweder ein Benutzer ändert die Auswahl zu Punkt 2 oder führe ich die Linie (Pseudo-Code):

combo.setSelection(2)

.. es scheint, als ob ich nicht in der Lage bin auseinander diese Ereignisse zu erzählen.

Das heißt, ich bin kein Swing-Experte mit allen Mitteln, so dass ich dachte, ich würde fragen.

Danke!

War es hilfreich?

Lösung

Die Aktion und Reaktion Gesetz ist ganz klar :). Wenn Sie versuchen, auf Veränderung zu reagieren besteht keine Notwendigkeit, zwischen Benutzer und Anwendung zu unterscheiden. Ich kann nur ein Anwendungsfall vorstellen, wo Sie brauchen, um „zu unterscheiden“. Der Fall, wo Anwendung einige Daten anzeigt. In diesem Fall haben Sie wahrscheinlich Datenmodell für Ihre Anwendung. Und es gibt auch einige Änderungsempfänger in diesem Modell und Anwendung GUI, indem Werte auf Komponenten reagieren. Und auch. Wenn der Benutzer auswählt, etwas in GUI-Komponente. Das Datenmodell wird durch Änderung Wert reagieren. In diesem Fall ist es einfach, eine Art von Nur-Lese-Zustand auf Datenmodell einzurichten, welches Modell Jedes Ereignis zu ignorieren aus beobachteten Objekten benachrichtigt kommen. Diese Mitteilung Satz sollte in EDT laufen und es gibt kein Problem mit markieren. Kleines Beispiel:

class ApplicationDataModel {

    private Flag current = Flag.RW;

    public void setData(ApplicationData data) {
        current = Flag.RO;
        setDataImpl(data);
        notifyObservers();
        current = Flag.RW;
    }

    public void reaction(Event e) {
        if (flag = Flag.RO) return;
        ...
    }

}

Seien Sie vorsichtig mit Beflaggung und vergessen Sie nicht über Threading. Wenn Sie setData von einem anderen Thread dann EDT rufen Sie in Schwierigkeiten gehen. Na sicher. Die Extraktion von ApplicationData Objekt in anderem Thread ausgeführt werden sollte;). In der Regel überdenken Design Ihrer Anwendung.

Andere Tipps

Ob der Benutzer Punkt 2, oder die API-Aufrufe setSelection (2), wird die Veranstaltung des gleichen angezeigt.

Die Lösung für Ihr Problem in sein könnten wieder zu denken, was Sie die itemStateChanged Code soll, wenn sich die Auswahl ändert tun. Warum sollte Ihre Anwendung funktionieren anders unter jeder Bedingung? Vielleicht gibt es Ähnlichkeiten, die Sie zu Ihrem Vorteil nutzen können.

Seien Sie vorsichtig, wenn Sie Flags verwenden. Die itemStateChanged Veranstaltung wird auf dem Event Dispatch Thread auftreten, die ein anderer Thread als der befindet, auf das Sie den Zustand des Flag gesetzt haben. Dies würde bedeuten, dass eine Fahne mit nicht 100% zuverlässig sein kann.

Sie können eine Flagge in Ihrem Code festlegen, bevor Sie die Auswahl festgelegt, und dann prüfen, für diese Flagge im Hörer (und ungesetzt das Flag, wenn es gesetzt ist) ...

Es kann eine bessere Art und Weise, da Java 6 sein, aber das ist die Art, wie ich es immer zu tun pflegte ...

[Bearbeiten] : Wie David weist darauf hin, müssen Sie das Flag setzen (und die Combo-Update) im EDT mit SwingUtilities.invokeLater oder ähnlich (Sie sollten dies trotzdem tun, wie Sie ein UI-Steuerelement ändern)

Wenn Sie auseinander, die Ereignisse zu erzählen, dann ist es wahrscheinlich etwas über Ihr Design, das ein Umdenken braucht. Der ganze Sinn der MVC ist Änderungen an dem Modell von den tatsächlichen Mausklicks des Benutzers zu entkoppeln.

Vielleicht sollten Sie die Frage in Bezug auf die neu formulieren Warum Sie würde immer zwischen diesen beiden Situationen unterscheiden wollen. Wir könnten dann einige Hinweise auf eine andere Art und Weise bereitzustellen, das Ziel zu erreichen.

So vermute ich, Sie die Benutzerauswahl wollen eine Aktion eher als nur eine einfache alte direkte Zustandsänderung durchzuführen. Dies ist ein Problem durch eine begrenzte Flexibilität verursacht (Flexibilität ist immer begrenzt gehen wird, vor allem, wenn Sie Flexibilität in anderen Richtungen haben).

Mein Vorschlag:

Zum einen immer geradeaus auf der Verwendung Modell in Swing. Die Widgets sind viel zu kompliziert, und Sie wollen andere Sorgen aufgeteilt werden. Zum Glück Swing ist schon da mit seinen Modellen.

Ein übliches Muster ist Delegation zwischen den Modellen zu haben. Also in diesem Fall haben Sie das „echte“ Standardmodell, das Ihre Daten enthält. Legen Sie zwischen dem JComboBox und realen ComboBoxModel und Delegieren ComboBoxModel, die Aktionen auf Zustandsänderung Anweisungen ausführt. Ihr Anwendungscode sollte die JComboBox ignorieren und fahren Sie geradeaus für die reale ComboBoxModel unter Umgehung des delegierenden Modell. So in einem Diagramm:

User -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- Application code
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top