TP5 POO: MVC et interface graphqiue

Objectif

Dans ce TP, nous allons reprendre le modèle développé lors du TP4 (avec les moutons) et créer une interface graphique permettant contrôler les différents paramètres de la simulation. On se basera sur le principe de “Modèle – Vue – Contrôleur” vu en cours.

Récupération du code

L’ensemble du code est disponible dans un repo indépendant. Vous pouvez le récupérer directement avec IntelliJ avec “New Project from version control” ou en le téléchargeant depuis gitlab.

Architecture générale

L’architecture du projet est déjà fournie. Le package fr.upsaclay.bibs.fieldsystem.sheepfield est globalement la correction du TP4. (On a très légèrement changé la classe Grass pour utiliser la même probabilité pour toutes les instances).

Nouveaux packages

L’application contient deux nouveaux packages :

Le contrôleur

La classe principale est FieldController qui sera en charge de créer la vue, de l’initialiser, de créer et de paramétrer le modèle en fonction des actions reçues par l’utilisateur.

Le package contient aussi quelques autres classes :

La Vue

Démarrage et affichage

Premier lancement

Lancez l’application : vous devez voir apparaître la fenêtre principale avec un panneau de contrôle sur la droite.

Le panneau contient un bouton “Start”. Si vous cliquez sur “Start” rien ne se passe.

Comprendre

Notre but pour l’instant est de faire disparaître le panneau de management initial quand on clique sur “Start”. Pour cela, il faut déjà comprendre qui crée les éléments et où.

Regardez la classe SwingFieldView et répondez à ces questions (pour vous, dans votre tête, sur un papier, comme vous voulez) : * où est déclarés le panneau initialPanel ? * où est-il créé ? * où est-il ajouté à la fenêtre principale ? (Est-il ajouté directement ? Est-il ajouté à u autre panneau ?) * Même question pour initialStartButton

Enfin, regardez la méthode drawSimulationInitView : par qui est-elle appelée et quand ? Que se passe-t-il si vous changez la visibilité de initialPanel à false ? (Remettez à true après)

Exercice Implémenter une méthode private void drawSimulationPlayView() dans SwingFieldView qui ne contient qu’une seule ligne mettant la visibilité de initialPanel à false. Complétez la méthode setViewState pour appeler cette méthode lorsque l’on reçoit l’état SIMULATION_PLAY. Vérifiez que cela fonctionne en modifiant l’état dessiné dans la méthode initialize du contrôleur. (Puis remettez l’ancienne initialisation)

Agir

Faîtes en sorte que le panneau contenant “Start” disparaisse quand on appuie sur le bouton, pour cela il faut :

Gestion des affichages

En vous inspirant ce qui a été fait :

Le fonctionnement est le suivant :

Au départ on voit le initPanel. Quand on clique sur “Start”, le playPanel s’affiche. Quand on clique sur “Pause”, le pausePanel s’affiche. Si on clique sur “Start”, on revient au playPanel, si on clique sur “Quit”, on revient à initPanel.

Pour cela, il faut

Lancement de la simulation

Création du champ

Le modèle, c’est à dire l’instance de Field, n’est pas créée par défaut à la création du contrôleur : en effet, on veut se laisser la possibilité de modifier certains paramètres avant la création de l’objet.

En fait, on veut créer le modèle au moment du lancement quand on appuie sur “Start”. Pour cela, dans le contrôleur, on va rajouter des actions au moment de l’évènement INITIAL_START :

Si vous faites tout ça, vous devez voir apparaître votre champ quand vous appuyez sur “Start”

Suppression du champ

De la même façon, on veut que quand on clique sur “Quit” le système soit réinitialisé (supprimé) pour qu’on puisse relancer la simulation avec de nouveau paramètres.

Adaptez l’action correspondante pour que :

(vous pouvez utiliser la méthode quit de FieldController et l’appeler depuis receiveAction

Vous devez voir le champ disparaître quand vous cliquez sur “Quit” et de nouveau avoir un rectangle blanc.

Lancer la simulation

Rappel : le modèle de simulation est un champ contenant des éléments (l’herbe, les moutons, les loups) qui évoluent par étape. Pour observer les évolutions, il faut donc pouvoir appeler la méthode d’évolution du système à intervalle régulier.

Pour ce faire, la vue utilise un objet Timer défini par Swing . On a déjà déclaré l’objet timer dans SwingFieldView et on l’a instancié dans le constructeur.

Un Timer est en fait relié à un ActionListener (comme un bouton), l’action sera envoyée à intervalles régulier (comme si quelqu’un appuyait sur un bouton toutes les x millisecondes). On a défini l’action EVOLVE dans la liste des FieldAction qui correspond à ce que l’on veut. Pour que ça marche, il faut

Côté vue :

Côté contrôleur :

Mise à jour des paramètres

On souhaite rajouter des paramètres à l’initialisation pour contrôler le nombre de moutons et de loups. Pour cela, on va utiliser la classe FieldParameter que j’ai écrite : c’est un JPanel un peu améliorer pour gérer l’interaction entre un champ de texte et un bouton.

Ajouter les paramètres à la vue

Etape 1 Implanter la méthode createParameter dans SwingFieldView : la méthode reçoit un texte à afficher (par exemple “Nombre de moutons”) et une action correspondante. Il faut utiliser ces deux entrées pour créer les 3 paramètres du constructeur de FieldParameter : label, defaultValue, et verifier

Etape 2 : Ajouter deux FieldParameter, un pour les moutons, un pour les loups, à initPanel au moment de l’initialisation. Les deux actions correspondantes sont INITIAL_SHEEPS et INITIAL_WOLVES.

Vous devriez voir des champs de texte avec des boutons “ok” apparaître au début de l’application. Si vous modifiez le texte, il passe en rouge. Le bouton ne devient actif que quand le texte a été modifié ET que la valeur est un entier correct.

Cependant, rien ne se passe quand on clique sur “ok” (le nombre de moutons / loups au lancement de la simulation n’est pas modifié). On va corriger ça

Implanter l’action correspondante

Côté contrôleur :

Côté vue :

Tout le reste

En vous inspirant de tout ce qui est déjà implanté, ajouter de quoi contrôler l’ensemble des paramètres de la simulation :

Pour cela, il vous faut ajouter les actions nécessaires dans FieldAction, les composants nécessaires dans la vue, un état supplémentaire de la vue pour le panneau de management, les réactions nécessaires dans le contrôleur et relier tout ça.