Si les composants swing sont basés sur l'architecture M/V/C, il n'en reste pas moins difficile d'architecturer une application Swing complète en M/V/C. Contrairement à JavaFx, dont la notion de Property incite à programmer proprement, Swing propose une série très disparate de modèles, dont certains sont trop complexes pour les use-case de base (je pense en particulier aux champs textes, et à l'absence d'un champ de saisie formatée décent).
Dans de nombreux cas, ça ne prête pas trop à conséquence. L'architecture Modèle/Vue/Présentateur, par exemple, est plus simple et plus adaptée aux formulaires que le MVC. Celui-ci, d'ailleurs, ne se conçoit raisonnablement que dans une approve M/VM/V/C avec un view model.
Nous avons réalisé un projet, swing-model-view-controller-example, qui est un peu un exercice de style. L'idée était de voir, en utilisant diverses bibliothèques, comment réaliser en MVC « pur » une application CRUD classique. C'est un work in progress, avec quelques manques :
- pas de gestion des traitements asynchrones ;
- des choses à nettoyer
- les données sont stockées en mémoire (quand on charge une table, elle est lue dans sa totalité).
Les projets
Je propose actuellement deux implémentations
- editor-swingfx
utilise deux bibliothèques
- SwingFX, portage des propriétés JavaFx à Swing ;
- pour les collections, GlazedLists.
- editor-jgoodies
- utilise les bindings JGoodies, dans les dernières versions open source. Ça gère tous les composants ; SwingFx est plus moderne, mais est limité. Le problème de JGoodies est que son modèle commercial ne permet plus qu'il soit distribué comme open source ; les dernières versions ne sont donc pas disponibles. L'ancien modèle, fondé sur la vente de services (formations au framework) et de donations, ne tient plus maintenant que l'audience de Swing est restreinte.
Architecture globale
Dans l'ensemble, le principe est identique pour les deux projets.
Un modèle partagé contient les listes de données à afficher par tous les formulaire ; chaque formulaire a par ailleurs son propre modèle. le programme se décompose en trois éléments :
- un affichage global de la liste, permettant également la suppression d'éléments ;
- un formulaire de création d'éléments ;
- un formulaire d'édition et de navigation entre les éléments.
Chacun de ces formulaires dispose d'un contrôleur et est lié à un ViewModel spécifique, lui-même relié au modèle partagé.
Dans chaque formulaire, chaque élément est lié à un élément du ViewModel ; les propriétés de certains éléments, comme l'activation d'un bouton, sont également liées à des propriétés booléennes du ViewModel.
Il convient de noter que l'on pourrait aussi envisager d'utiliser des objets Action. Logiquement, ceux-ci pourraient trouver leur place dans le ViewModel. Toutefois, une action peut nécessiter des éléments graphiques (par exemple, un sélecteur de fichiers), ce qui serait architecturalement inapproprié si elle se trouvait dans le ViewModel. Dans ce cas, la solution consisterait à abstraire l'élément graphique en question via une interface, mais cette approche s'avérerait quelque peu lourde.
Projets connexes
La combinaison de RxJava et RxSwing offre une solution possible pour des applications MVC complètes en Swing. Cette piste a été approfondie par Peti Koch dans le projet Java MVVM with Swing, RxJava and RxSwing, qui traite de cas d'utilisation assez complexes (tâches concurrentes multiples). M. Koch met toutefois en garde : ne pas utiliser en production, car certains problèmes restent à résoudre.
Évidemment, tout cela est quelque peu dépassé.