2009-12-04 3 views
6

Dans une application Java "sérieuse", vous aurez des modèles derrière plusieurs de vos éléments GUI: A DocumentModel soutenant un JEditorPane, par exemple, ou un ListModel derrière un JList.Est-il possible de changer un modèle en dehors du thread de travail Swing?

On nous dit toujours de ne pas effectuer de modifications de l'interface graphique depuis l'extérieur du thread de travail Swing et de lui donner SwingUtilities.invoke...() pour contourner ce problème. Bien, je peux vivre avec ça! C'est certainement nécessaire (et fonctionne bien) lorsque vous modifiez directement les attributs des composants de l'interface graphique.

Idéalement, la plupart de mes changements GUI-visibles seront de modèles, pas de JComponents, de toute façon. Mais parce qu'ils sont visibles sur l'interface graphique, sont-ils "comptés" comme des changements d'interface graphique? C'est à dire. est-ce que les événements de changement changent et les écouteurs fournissent le découplage nécessaire, ou les changements de modèle doivent-ils également être inclus dans invoke...()?

Probablement un vieux chapeau pour les pros de Swing, mais je n'ai pas trouvé de référence qui indique clairement d'une façon ou d'une autre.

Répondre

5

Généralement, le changement de modèle doit être enveloppé dans invokeLater (...). Il n'y a pas de découplage dans le code du modèle de la plupart des classes de swing dans lesquelles j'ai regardé. Il est à vous de créer un modèle qui pourrait contenir les appels en vérifiant que les modifications de l'interface graphique sont effectuées sur le thread Dispatcher Event.

+1

-1: Pas la réponse que je voulais entendre! (Je plaisante, +1) Merci! –

+1

En ce qui concerne le débogage des problèmes de thread Swing, je recommande fortement ce lien: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html Le CheckThreadViolationRepaintManager m'a fait gagner beaucoup de temps. –

+1

Le texte Swing * déplace * certains * événements vers l'EDT. Bien sûr, ça fait juste un plus gros gâchis. –

2

Si les événements sont déclenchés depuis l'EDT et mettent à jour les composants Swing qui vont poser un problème.

En mode Swing, les événements peuvent (!) Être transférés vers l'EDT. Cela rend les tests difficiles. Sans surprise, l'API n'est pas utile dans un environnement multithread. Donc: Le plus facile garder le modèle sur l'EDT et les autres threads doivent passer des messages (impliquant EventQueue.invokeLater). Alternativement, vous pouvez mettre un gros verrou autour de tout, ce qui est plus difficile (et vous aurez probablement encore besoin de passer des choses à l'EDT). Tentative de microsynchronisation est très difficile.

+1

"La microsynchronisation est très difficile." : Je suis totalement d'accord avec ce point. J'ai supprimé tous mes mots-clés synchronisés et vérifié plus attentivement que toutes les modifications sur l'interface graphique (et les modèles des éléments de l'interface graphique) ont été effectuées sur l'EDT. –

+1

J'avais peur de ça. Cela signifie que mes modèles deviennent techniquement partie de l'interface graphique et doivent être traités comme faisant partie de celle-ci à cette fin. Il ne semble pas "propre" du point de vue de la superposition/encapsulation, et (c'est ma plus grande objection, bien sûr) c'est plus de travail! +1, merci! –

2

Oui, c'est tout à fait OK.

Bien qu'il soit vrai, vous ne devez pas modifier les composants Swing en dehors de l'EDT. Vous pouvez certainement apporter des modifications à leurs modèles en dehors de l'EDT.

Si vous avez correctement câblé les modèles sur vos composants Swing, la mise à jour de la vue et donc la programmation EDT se feront presque automatiquement.

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

Voir la partie sur le modèle JavaBeans événement.

Voici comment les modèles communiquent leur état modifié à l'interface utilisateur graphique en toute sécurité. Lorsque vous créez de nouveaux composants GUI, vous devez suivre ce modèle de conception.

Notez également la distinction entre les modèles d'état GUI et les modèles de données d'application.

Les modifications apportées aux modèles à partir de l'EDT nécessitent toujours des précautions. En fait, la plupart des problèmes de Swing surviennent lorsque le programmeur modifie un modèle dans l'EDT alors qu'ils devraient le modifier à partir d'un thread séparé.(Problème infâme de l'IUG gelé)

De même, rien de tout cela n'empêche d'être pleinement conscient des pièges multi-threads typiques.

Mais vous pouvez très certainement apporter des modifications à un JTableModel depuis l'extérieur de l'EDT.