2009-12-04 7 views
6

In einer "seriösen" Java-GUI-App haben Sie Modelle hinter vielen Ihrer GUI-Elemente: A DocumentModel unterstützt zum Beispiel eine JEditorPane oder eine ListModel hinter einer JList.Ist es in Ordnung, ein Modell außerhalb des Swing-Arbeitsthreads zu ändern?

Es wird uns immer gesagt, dass wir keine GUI-Änderungen von außerhalb des Swing-Worker-Threads vornehmen und SwingUtilities.invoke...() dafür geben müssen. Gut, damit kann ich leben! Es ist sicherlich notwendig (und funktioniert gut), wenn Attribute von GUI-Komponenten direkt geändert werden.

Im Idealfall werden die meisten von meiner GUI sichtbaren Änderungen für Modelle und nicht für JComponents gelten. Aber weil sie GUI-sichtbar sind, "zählen" sie als GUI-Änderungen? I.e. Ändern Sie Ereignisse und Listener bieten die notwendige Entkopplung, oder müssen Modelländerungen auch in invoke...() gewickelt werden?

Wahrscheinlich alter Hut, um Pros zu schwingen, aber ich war nicht in der Lage, irgendeinen Hinweis zu finden, der eindeutig auf die eine oder andere Weise aussagt.

Antwort

5

Im Allgemeinen muss die Modelländerung in invokeLater (...) eingeschlossen werden. Es gibt keine Entkopplung im Modellcode der meisten Swing-Klassen, in denen ich gesucht habe.

Es liegt an Ihnen, ein Modell zu erstellen, das die Aufrufe enthalten kann, die überprüfen, ob GUI-Änderungen am Event Dispatcher-Thread vorgenommen wurden.

+1

-1: Nicht die Antwort, die ich hören wollte! (Nur Spaß, +1) Danke! –

+1

In Bezug auf das Debugging von Swing-Threads empfehle ich dringend diesen Link: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html Der CheckThreadViolationRepaintManager hat mir viel Zeit gespart. –

+1

Swing-Text bewirkt * einige * Verschiebung von Ereignissen zum EDT. Natürlich macht es nur ein größeres Durcheinander. –

2

Wenn die Ereignisse aus dem EDT ausgelöst werden und Swing-Komponenten aktualisieren, wird das ein Problem sein.

Im Swing-Text können Ereignisse (oder nicht) in den EDT übertragen werden. Dies macht Tests schwierig. Es überrascht nicht, dass die API in einer Multithreadumgebung nicht nützlich ist.

Also: Am einfachsten halten Sie das Modell auf dem EDT und andere Threads sollten Nachrichten weitergeben (einschließlich EventQueue.invokeLater). Alternativ können Sie eine große Sperre um alles legen, was schwieriger ist (und Sie müssen wahrscheinlich noch Dinge an die EDT übergeben). Mikrosynchronisation ist sehr schwierig.

+1

"Mikrosynchronisation ist sehr schwierig." : Ich stimme diesem Punkt vollkommen zu. Ich entfernte alle meine synchronisierten Schlüsselwörter und überprüfte genauer, dass jede Änderung auf der GUI (und Modelle der Elemente der GUI) auf dem EDT gemacht wurden. –

+1

Ich hatte Angst davor. Das bedeutet, dass meine Modelle technisch Teil der GUI werden und zu diesem Zweck als Teil davon behandelt werden müssen. Es scheint nicht "sauber" zu sein von einem Layering/Verkapselungspunkt, und (das ist natürlich mein größter Einwand) es ist mehr Arbeit! +1, danke! –

2

Ja, es ist auf jeden Fall in Ordnung.

Während es wahr ist, sollten Sie Swing-Komponenten nicht außerhalb des EDT ändern. Sie können sicherlich Änderungen an ihren Modellen außerhalb des EDT vornehmen.

Wenn Sie die Modelle korrekt an Ihre Swing-Komponenten angeschlossen haben, erfolgt die Aktualisierung der Ansicht und damit die EDT-Planung fast automatisch.

See: http://java.sun.com/products/jfc/tsc/articles/architecture/#roots

Siehe Teil über Java Beans Ereignismodell.

So kommunizieren Modelle ihren geänderten Status EDT-sicher an die GUI. Beim Erstellen neuer GUI-Komponenten sollten Sie diesem Entwurfsmuster folgen.

Beachten Sie auch die Unterscheidung zwischen GUI-Zustandsmodellen und Anwendungsdatenmodellen.

Änderungen an Modellen aus dem EDT müssen weiterhin sorgfältig durchgeführt werden. In der Tat passieren die meisten Swing-Probleme, wenn der Programmierer ein Modell im EDT modifiziert, wenn sie es von einem separaten Thread modifizieren sollen.(Berüchtigtes gefrorenes GUI-Problem)

Auch nichts davon schließt aus, dass man sich der typischen Multithreading-Fallstricke bewusst ist.

Aber Sie können definitiv Änderungen an einem JTableModel von außerhalb des EDT vornehmen.

Verwandte Themen