IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

MVC en swing : Qu'est-ce qui va dans la vue et le controleur


Sujet :

AWT/Swing Java

  1. #1
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut MVC en swing : Qu'est-ce qui va dans la vue et le controleur
    Bonjour,

    J'ai rarement eu l'occasion de faire des applications graphiques type swing, et je regarderai quelques tutoriels à droite à gauche sur le respect de MVC avec swing.
    Et je suis tombé sur plusieurs cas qui fait que je ne sais pas exactement ce qui doit aller dans la vue et ce qui doit aller dans le controleur.

    D'ailleurs, ça m'embête un peu, car je me dis que cette architecture est tellement nase que quelque chose doit m'échapper .


    Imaginons que sur ma vue, j'ai un simple bouton, qui peut par exemple amener à l'ouverture de fichier (Fenêtre de dialogue où l'utilisateur choisi son fichier).

    Cas 1 :

    D'un côté, je vois des tutos qui mettent l'ActionListener du bouton directement sur la vue, puis passe par le contrôleur pour déclencher le traitement (ou l'action).
    => ce qui me dérange avec cette aspect, c'est finalement que la vue ne joue pas uniquement un rôle de vue, mais aussi de composant qui écoute. Et la demande de traitement au contrôleur est finalement mise dans la vue.
    Mais je ne crois pas que l'on puisse faire autrement pour certains type de traitement, comme les drag&drop de fichiers.

    D'un autre côté, je vois des tutos où c'est le contrôleur qui ajoute l'ActionListener sur le bouton de la vue
    => et là, ce qui me dérange, c'est que le contrôleur est au courant de l'implémentation de la vue (il sait déjà a priori que c'est du swing).

    Cas 2 :
    Ensuite, quand l'utiilisateur clique sur le bouton, cela ouvre une fenêtre attachée à l'autre vue. Mais qui s'occupe de l'attachement de la fenêtre ?
    - si c'est la vue, il faut y aller à coup d'instanceof, ce qui fait que ça ne respecte pas vraiment le principe de Liskov (même s'il y a un simple "attachView" sur l'interface de la vue)
    - si c'est le controleur, on retombe sur le cas où le controleûr est au courant que c'est du swing derrière



    Du coup, quelle stratégie adopter pour ces 2 cas ?


    Merci
    Je ne répondrai à aucune question technique en privé

  2. #2
    Membre confirmé
    Avatar de william44290
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Juin 2009
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 400
    Points : 575
    Points
    575
    Par défaut
    Pour les simples fênetres je code tout dans le panel qui devient un VC. (le cas numéro 1)

    Pour les fênetres complexe je décompose. En particulier je dissocie en deux parties les Vues. Soit un panel d'affichage et un panel de bouton, une class métier typée controleur s'occupant d'instancier ces 2 vues et écoutants les boutons via une interface. Le Modèle n'étant qu'un mapping de table.

    Je ne comprends pas ton cas numéro 2.

    Sur le fond, le principe de découplage reste virtuel car d'une façon ou d'une autre le controleur dispose régulierement d'une référence sur la/les vues et sur le modéle.

  3. #3
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par william44290 Voir le message
    Sur le fond, le principe de découplage reste virtuel car d'une façon ou d'une autre le controleur dispose régulierement d'une référence sur la/les vues et sur le modéle.
    Le problème n'est pas d'avoir une référence, mais c'était de ne pas avoir à connaître l'implémentation.


    Soit un panel d'affichage et un panel de bouton, une class métier typée controleur s'occupant d'instancier ces 2 vues et écoutants les boutons via une interface
    Donc, dans ton cas, c'est le controleur qui ajoute les listeners sur la vue ?





    Pour être plus précis, pour le cas 1, je ne savais pas s'il fallait faire (je n'ai pas mis les listeners sur le modèle) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    public interface MaVue {
      ....
    }
     
    public class SwingVue implements MaVue {
       JButton button = new JButton("etc");
       ....
       button.addActionListener(new ActionListener() {
          void run() {
              getController().executeAction(new MonAction(mesparamètres));
          }
       });
    }
     
    public Controlleur implements IController {
       MaVue vue = ViewFactory.get(MaVue.class);
       public void executeAction(Action a) {
           a.execute(); //pour simplifier
       }
    }
    Ou s'il fallait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    public interface MaVue {
      ....
    }
     
    public class SwingVue implements MaVue {
       JButton button = new JButton("etc");
    }
     
    public Controller implements IController {
       MaVue vue = ViewFactory.get(MaVue.class);
       public Controller() {
         ((SwingMaVue) vue).getJButton().addActionListener(new ActionListener() {
          void run() {
             Action a = new MonAction(mesparamètres));
             a.execute();
          }
       });
    }

    Pour le cas 2, si par exemple la vue principale est un JDesktopPane où l'on peut attacher d'autre vue. Cela correspond aux 2 cas suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    public interface SubView {
       void display();
    }
     
    public SwingOpenFileView implements SubView extends JDialog {
     ....
    }
     
    public interface MainView {
      public void attachSubView(SubView view);
    }
     
    public SwingMainView implements MainView extends JDesktopPane {
       //cette méthode peut être appelée au travers du controlleur
      public void attachSubView(SubView view) {
         if(view instanceof Component) 
            add((Component) view);
      }
    }
     
    public ControllerImpl implements Controller {
       ....
      public void attachSubView(SubView view) {
          getView().attachSubView(view); 
      }
    }
     
    public void OpenFileAction implements Action {
       //j'ai retiré le constructeur
       public void execute() {
            SwingOpenFileView v = new SwingOpenFileView(getController());
            getController().attachSubView(v);
       }
    }
    Ou :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public ControllerImpl implements Controller {
       ....
      public void attachSubView(SubView view) {
          if(getView() instanceof JDesktopPane && view instanceof Component) {
              ((JDesktopPane) getView()).add((Component) view);
          }
      }
    }
    A priori, je voterai pour les premiers exemples qui présentent moins de contraintes, mais je voulais être sûr car j'ai déjà vu le contraire.

    Enfin, à noter que je n'aime pas vraiment l'architecture MVC, donc j'essaye de l'adapter comme je veux
    Je ne répondrai à aucune question technique en privé

  4. #4
    Membre confirmé
    Avatar de william44290
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Juin 2009
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 400
    Points : 575
    Points
    575
    Par défaut
    Donc, dans ton cas, c'est le controleur qui ajoute les listeners sur la vue ?
    Oui, j'essaye de réaliser les vues les plus basiques possible.(Les demandes et critiques des utilisateur portent principalement sur ces dernières)

    pour le cas numéro 1 la version 1 est plus lisible mais la version 2 me semble plus conforme

    La vue qui appelle le controleur cela me semble anti-pattern.

    désolé pour le cas 2 cela me dépasse.

  5. #5
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par william44290 Voir le message
    La vue qui appelle le controleur cela me semble anti-pattern.
    C'est par exemple ce que l'on voyait ici :
    http://baptiste-wicht.developpez.com...ion/mvc/#LII-C
    Je ne répondrai à aucune question technique en privé

  6. #6
    Membre confirmé
    Avatar de william44290
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Juin 2009
    Messages
    400
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 400
    Points : 575
    Points
    575
    Par défaut
    pour ma part lorsque que je travaille avec des composants les actions opérées sur le composant modifie une property du composant.

    Le controleur qui a instancié le composant Ecoute le changement d'état du composant et interagi en conséquence.

    Le composant n'a aucun lien avec le controleur.(plus exactement il ne sait pas si un ou plusieurs controleur l'écoute)

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 838
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 838
    Points : 22 846
    Points
    22 846
    Billets dans le blog
    51
    Par défaut
    Alors pour rappel (deja mentionne dans un autre topic il y a qq mois) :

    - la plupart des composants Swing fournis par defaut : la vue EST le controlleur, Swing utilisant plutot M V+C que MVC. Le composant dispose donc un unique modele (M) et une unique UI Delegate (V+C). Le modele influe sur l'etat de l'UI tandis que l'UI permet de modifier l'etat du modele.

    composant -> M -> V+C -> M

    Les codes sources des UI de base sont dispo dans les packages javax.swing.plaf.basic et javax.swing.plaf.metal (voir sources.zip a la racine du repertoire d'installation du JDK). Par exemple, il peut etre interressant et enrichissant d'aller lire le code source de BasicSliderUI si on desire implementer de nouveaux composants.

    Quand on change de LnF via l'UIManager par exemple, on change l'UI Delegate de chacun des composants affiches.

    - JavaFX utilise VC : il n'y a pas de modele dedie (pour le moment) et chaque controle JavaFX (le nom des composants en JavaFX) dispose d'une unique Skin (V) se charge de l'apparence et qui elle-meme delegue le comportement a un unique Behavior (C). On peut egalement faire V+C en faisant que la skin gere directement le comportement mais ce n'est pas trop recommande (certaines choses comme le fait qu'il n'y a pas de propagation des evenements claviers lorsque le controle est desactive sont gerees automatiquement par le Behavior).

    controle -> V -> C -> controle

    C'est comme cela que sont implementees les composants et les controles de base en Swing et JavaFX. Apres pour des interfaces plus complexes, a toi de voir si tu veux implementer une separation stricte des divers composantes M V et C.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Pour une explication un peu fine de l'application de ces patterns en Swing:
    http://www.jgoodies.com/articles/binding.pdf
    http://www.jgoodies.com/articles/pat...nd-binding.pdf

    Sachant qu'in fine l'auteur prêche pour sa paroisse à savoir le pattern MVP au lieu du MVC. Le MVP décorrélant totalement la vue du modèle, la vue accédent au modèle via le presenter (une sorte de contrôleur sous stéroïdes).

    Bon là c'est vite fait car j'ai pas trop de temps devant moi, j'reviens dès que j'en ai un peu plus.
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  9. #9
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Bon, en gros, il n'y a pas vraiment de règle
    Je ne répondrai à aucune question technique en privé

  10. #10
    Membre actif Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Points : 275
    Points
    275
    Par défaut
    Citation Envoyé par millie Voir le message
    Bon, en gros, il n'y a pas vraiment de règle
    Le but du contrôleur est la traduction des actions de l'utilisateur en actions à exécuter par le modèle. L'attachement d'un ActionListener ou d'une fenêtre n'étant généralement pas une action qui intéresse le modèle, il n'y a pas de raison pour placer ça dans le contrôleur (d'ailleur, je ne vois pas où "il faut y aller à coup d'instanceof" dans ce cas).

  11. #11
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par uhrand Voir le message
    il n'y a pas de raison pour placer ça dans le contrôleur (d'ailleur, je ne vois pas où "il faut y aller à coup d'instanceof" dans ce cas).

    En fait, je n'ai pas parlé de instanceof pour ce cas là.
    Le point qui m'embêtait avec ça, c'était juste que la vue n'est pas seulement une vue, c'est une vue qui écoute et qui transmet les demandes de traitements. Du coup, le nom me semble assez mal choisi.
    Je ne répondrai à aucune question technique en privé

  12. #12
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 838
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 838
    Points : 22 846
    Points
    22 846
    Billets dans le blog
    51
    Par défaut
    Enfin bon quand on va lire les sources de l'API c'est un peu la foire à instanceof chez Sun...

    A noter que les UI des divers AbstractButton (JButton, JRadioButton, etc...) disposent bien d'une séparation entre V et C contrairement à d'autre JComponent. Et ici c'est à nouveau la vue qui instancie le contrôleur. Il faut dire aussi que le controleur d'un bouton est plutot simpliste (juste vérification des touches du clavier et des clics sur toute la surface du composant) par rapport à ce que peut être celui d'une vue plus complexe comme peut l'être le controleur d'un JSlider qui dépent fortement de la forme de son apparence.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  13. #13
    Membre actif Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Points : 275
    Points
    275
    Par défaut
    Citation Envoyé par millie Voir le message
    la vue n'est pas seulement une vue, c'est une vue qui écoute
    C'est courant d'avoir une vue qui écoute, car elle écoute souvent le modèle. Alternativement, nous pourrions faire implémenter l'ActionListener par le contrôleur. Dans ce cas, c'est le contrôleur qui écoute directement. Mais ça change rien au principe MVC.

  14. #14
    Membre averti
    Avatar de Chatanga
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 211
    Points : 346
    Points
    346
    Par défaut
    Dans le monde des IHM, le MVC se décline en pratique récursivement de la manière suivante :

    V' = M + V + C

    Voire, dans le cas de Swing notamment :

    V' = M + (V + C)

    Avec ce découpage de Swing et en imaginant une application basique, on pourrait obtenir le résultat suivant :

    MonApplication(V) = MonModele(M) + MonFormulaire(V) + MonControlleurFormulaire(C)
    MonFormulaire(V) = JComboBox(V) + ...(V) + ...(V)
    JComboBox(V) = ComboBoxModel(M) + ComboBoxUI(V+C)

    Remarque : personnellement, je crée souvent intégralement mes vues applicatives (ici MonFormulaire) sous NetBeans sans toucher au code (donc sans aucun binding).

    Pour détailler le cas d'une JComboBox, quand cette dernière installe son ComponentUI (qu'elle n'instancie d'ailleurs pas, mais dont elle demande simplement une instance appropriée à l'UIManager), elle ignore ce qu'il fait concrètement (elle n'utilise d'ailleurs même pas le fait que c'est un ComboBoxUI). Une JComboBox ignore ainsi que, pour la plupart des Look And Feel, l'instance de ComboBoxUI va lui ajouter un champ de texte, un bouton, un menu surgissant et câbler tout se joli monde. De fait, c'est bien le contrôleur le chef d'orchestre, le JComponent englobant (la JComboBox ici) n'étant qu'une coquille vide pour le MVC (pour ce qui est de la délégation du rendu, c'est autre chose). Néanmoins, comme tout ce petit monde est finalement caché dans la JComboBox, on peut quand même dire que, dans Swing, vue et contrôleur sont fusionnés, mais sans pour autant remettre en cause l'approche MVC.

    Sachant cela, on peut dire que la vue ne doit jamais connaître son modèle, que seul le controleur doit pouvoir le faire, quitte à l'embarquer dans la vue pour donner la sensation suivante.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new JComponentX(new Model()); // Le composant Swing "observe" le modèle.
    D'un certaine manière, tout se résume à une question de perspective. Là où le distinguo doit cependant s'opérer clairement, c'est lorsqu'il s'agit d'une vue et d'un modèle métier.

    UNE VUE NE DOIT JAMAIS ACCEDER DIRECTEMENT A UN MODELE METIER, C'EST A UN CONTROLEUR DE LIER LES DEUX.

    Par exemple, une vue géographique a le droit de manipuler apparemment directement un modèle graphique interne dont les objets seraient des formes géoréférencées, mais ne devrait en aucun cas jouer directement avec le modèle de données métier de l'application dont les objets seraient, par exemple, des voitures évoluant sur des routes. Un contrôleur s'impose pour connecter les deux.

  15. #15
    Membre actif Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Points : 275
    Points
    275
    Par défaut
    Citation Envoyé par Chatanga Voir le message
    UNE VUE NE DOIT JAMAIS ACCEDER DIRECTEMENT A UN MODELE METIER, C'EST A UN CONTROLEUR DE LIER LES DEUX.
    Ca c'est une mise en œuvre plus récente de la conception MVC. Elle place le contrôleur entre le modèle et la vue. La principale différence entre cette conception et la version plus traditionnelle de MVC est que les notifications de modifications d'état des objets de modèle sont communiquées à la vue par le contrôleur. Par conséquent, le contrôleur sert d'intermédiaire pour le flux de données entre le modèle et la vue dans les deux directions. Les objets d'affichage, comme toujours, utilisent le contrôleur pour traduire les actions de l'utilisateur en mises à jour de propriétés du modèle. Mais en plus, les modifications d'état du modèle sont communiquées à la vue par le biais d'objets de contrôleur d'une application. Cet MVC modifié permet de découpler plus complètement le modèle de la vue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 29/02/2008, 15h27
  2. qu'est-ce qui cloche dans ma requete select??
    Par a-chan dans le forum Langage SQL
    Réponses: 3
    Dernier message: 07/07/2005, 12h35
  3. qu'est-ce qui cloche dans ma requete?
    Par a-chan dans le forum Langage SQL
    Réponses: 4
    Dernier message: 20/06/2005, 10h02
  4. Réponses: 1
    Dernier message: 21/02/2005, 13h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo