Introduction

Horaires des TP

  • vendredi 6 mai, 13h30–16h30
  • jeudi 19 mai, 9h30–12h30
  • vendredi 20 mai, 13h30–16h30
  • mercredi 25 mai, 9h30–12h30

Équipe enseignante

Responsable du cours – Cédric Fleury
Chargés de TD/TP – Oleksandr Zinenko, Arnaud Prouzeau.

Travaux dirigés

Les exercices ont été conçus par Nicolas Roussel et ont été adaptés plusieurs fois par les membres de l’équipe HCC. Vous pouvez en trouver les solutions sur Internet, mais elles contiennent de subtiles différences, connues des enseignants. Vous êtes invités à écrire vos solutions vous-même pour apprendre les techniques nécessaires pour le projet.

1a. Mise en page des interfaces

Les diaporamas présentés en TD.

Le but de cet exercice est de créer un convertisseur de température contenant :

  • deux labels “Celsius” et “Fahrenheit”,
  • deux champs textuels qui servent à la fois pour l’entrée et pour la sortie des valeurs de température,
  • deux boutons, l’un effaçant les valeurs des champs textuels; l’autre fermant la fenêtre.

Déroulement de l’exercice :

  1. Téléchargez le fichier TempConverter.java.

  2. Complétez la fonction init() dans ce fichier en utilisant la classe JPanel et les gestionnaires de mise en page (layout managers) afin d’obtenir la fenêtre ci-dessous. N’oubliez pas d’initialiser les champs et les boutons. Layout

  3. Vérifiez que les éléments de l’interface (widgets) sont bien alignés et que leurs positions restent consistants quand vous redimensionnez la fenêtre.

1b. Réaction aux entrées de l’utilisateur

Les diaporamas présentés en TD.

Continuez de travailler sur le convertisseur de température. Après la mise en page des éléments de l’interface graphique, vous pouvez rajouter des interactions. Pour le faire, suivez les étapes suivantes :

  1. Le textFieldCListener lit une valeur flottante dans le champ Celsius quand l’utilisateur appuie sur la touche “Entrée”, l’interprète comme température Celsius et la convertit en Fahrenheit. Finalement il met le résultat dans le champ Fahrenheit. Associez ce listener au champ textuel contenant la valeur Celsius.

  2. Complétez le textFieldFListener de sorte qu’il fasse la conversion de Fahrenheit en Celsius. Associez-le au champ textuel contenant la valeur Fahrenheit.

  3. Le buttonCloseListener ferme la fenêtre. Associez-le au bouton “Close”.

  4. Complétez le buttonResetListener de sorte qu’il efface le texte dans les champs Celsius et Fahrenheit. Associez-le au bouton “Reset”.

  5. La conversion de température se passe quand l’utilisateur appuie sur la touche “Entrée”. Utilisez un KeyListener plutôt qu’un ActionListener pour refaire la conversion après chaque symbole entré par l’utilisateur.

2. Menus, Listes

Dans cet exercice, vous allez de nouveau utiliser les différents layout managers ainsi que les listeners pour développer un dialogue de sélection des fichiers.

FileSelector

Le dialogue affiche le contenu du dossier sélectionné. Les noms des sous-dossiers sont suivis par un slash (/) alors que ceux de fichiers simples restent inchangés. Le “menu” en haut de la fenêtre contient une liste des dossiers dans lesquels les programme se trouve actuellement, par exemple /, home/, etudiant/, td2/ pour représenter le chemin /home/etudiant/td2. Les boutons en bas servent à sélectionner un fichier ou à ouvrir un sous-dossier.

Déroulement de l’exercice :

  1. Téléchargez le fichier FileSelector.java.

  2. Modifiez ce fichier en utilisant les classes JComboBox, JList, JScrollPane et JButton afin d’obtenir une fenêtre ci-dessus. Vérifiez que leur positions restent consistants quand vous redimensionnez la fenêtre.

  3. Vérifiez que la sélection d’un sous-dossier met à jour le “menu” et la liste des fichiers.

  4. Faites le bouton “Open” actif si un fichier ou un sous-dossier est sélectionné dans la liste.

  5. Vérifiez que la fenêtre ferme quand l’utilisateur clique sur le bouton “Cancel”, ou quand il clique sur le bouton “Open” après avoir sélectionné un fichier (contrairement aux dossiers).

  6. Rajoutez la possibilité d’ouvrir un dossier par une double clique sur son nom dans la liste.

  7. N’oubliez pas de mettre à jour la liste et le “menu” quand un dossier est sélectionné dans le “menu”.

Pour les application réelles, on vous conseille d’utiliser la classe standard JFileChooser.

3. MVC : Modèle-Vue-Contrôleur

Les diaporamas présentés en TD.

L’objectif de cet exercice est de réaliser une interface permettant de choisir une couleur en manipulant ses composantes Rouge, Verte et Bleue à l’aide de potentiomètres ou en spécifiant leur valeur en hexadécimal. La couleur choisie est affichée dans un Panel dedié.

ColorChooser

Le code de selecteur des couleurs doit être séparé en trois parties selon le modèle MVC. Le but de ce modèle est de séparer les données, la méthode dont ces données sont visualisés et la technique d’interaction.

  1. Télécharger le fichier e4.zip.

  2. Dans un premier temps, nous allons réaliser un selecteur de couleur similaire à l’image ci-dessous :
    Color chooser basic
    La classe ColorChooser sera la classe contrôleur, elle fera donc le lien entre le model (ColorModel) et les vues (classes qui implémentent ColorView).

  3. Une manière de définir une couleur en informatique est de définir les proportions de rouge, vert et bleu qui la composent, c’est le codage RGB (Red Green Blue). Chaque composante est coder sur 8 bits et va donc de 0 à 255. Compléter la classe ColorModel pour qu’elle corresponde à ce model.

  4. Compléter les fonctions init() des classes SliderView et TextFieldView pour qu’elles ressemblent à l’interface recherchée.

  5. Rajouter les événements aux deux vues pour que chaque action modifie le modèle et soit transmis aux autres vues.

  6. Appeler le chargé de TD pour valider votre première version du ColorChooser.

  7. Nous allons maintenant ajouter 2 nouvelles vues :

    • Un champs de texte dans lequel la couleur est défini en hexadécimal
    • Un rectangle coloré avec la couleur correspondante Ajouter deux classes implémentant ColorView qui correspondent à ces deux vues.

Vous pouvez utiliser les méthodes Color.getRGB() et Integer.toHexString pour récuperer la représentation textuelle d’une couleur et la méthode Color.decode pour trouver la couleur définie par la valeur hexadécimal.

Il faut noter que Swing propose une classe JColorChooser qui permet de facilement choisir une couleur.

4. Dessin 2D

L’objectif de cet exercice est de créer un éditeur graphique 2D très simplifié afin de se familiariser avec le dessin 2D.

GraphicalEditor

  1. Téléchargez l’archive GraphicalEditor.zip qui contient les classes pour cet exercice : GraphicalEditor.java est l’interface graphique ; PersistentCanvas.java est une classe permettant de stocker les éléments du dessin ; CanvasItem.java est un élément abstrait du dessin ; RectangleItem.java est un élément réctangulaire qui hérite de la classe CanvasItem.

  2. Modifiez la classe GraphicalEditor afin qu’elle permette à l’utilisateur de choisir le mode en sélectionnant un bouton radio.

  3. Modifiez les classes GraphicalEditor et PersistentCanvas et rajoutez la possibilité de sélectionner un élément du dessin quand l’utilisateur clique dessus (mode Select/Mode). Pour cela, il est nécessaire de réaliser une méthode PersistentCanvas.getItemAt(Point p) qui gére la recherche d’élément couvrant les coordonnées du point.

  4. Rajoutez les actions aux boutons “Delete” et “Clone” pour effacer ou dupliquer l’élément sélectionné.

  5. Modifiez le MouseMotionListener dans la classe GraphicalEditor afin de permettre le déplacement des éléments du dessin.

  6. Rajoutez les widgets pour choisir la couleur du tracé et de remplissage des éléments graphiques. Utilisez une fenêtre de dialogue standard.

  7. Rajoutez les classes pour les formes autres qu’un rectangle (ellipse, ligne et une trace générique). Elles doivent avoir la même fonctionnalité que celle du rectangle en ce qui concerne le déplacement et les couleurs.

Projet

Modalités et dates limites

Le projet doit être principalement fait sur votre temps personnel, néanmoins les étudiants qui ont fini les exercices peuvent le faire pendant les TDs.

La version intermédiaire du projet doit être rendu avant la fin de la deuxième séance de TD. La soutenance aura lieu lors de la dernière scéance (mercredi 25 mai).

Le projet doit être par groupe de deux.

Sujet

Pendant ce projet, vous allez développer une version du jeu Threes pour l’environnement du bureau. Ce jeu est l’inspiration du très populaire jeu “2048” et consiste à bouger des tuiles contenant des nombres sur un tableau 4x4, à chaque fois que deux tuiles identiques se rencontrent, elles s’additionnent. Le jeu s’arrête lorsqu’une des tuiles à atteint la valeur principale.

JeuThrees

Ce projet vous permettra de vous familiariser avec la conception d’interfaces à l’aide de composants standard Java Swing, le dessin 2D, l’animation et l’entrée par le clavier ou la souris.

Principe du jeu

Le but du jeu est de déplacer des tuiles sur une grille, à chaque rencontre entre deux tuiles de même valeur elle s’additionnent, le jeu s’arrête lorsqu’on a atteint une valeur maximale donnée. Le jeu commence avec un tableau contenant 4-6 tuiles portant le nombre “1” ou “2” placées dans les cases aléatoires du tableau. Le joueur peut demander le déplacement dans l’une de quatre directions : à gauche, à droite, en haut ou en bas. Ce mouvement concerne toutes les tuiles. Pour chaque tuile, trois cas sont possibles :

  • la case en direction de mouvement est vide – la tuile est déplacée dans cette case ;
  • la case en direction de mouvement est occupé, mais la tuile qui l’occupe peut être déplacée dans la direction de mouvement – les deux tuiles sont déplacées ; (ce cas applique aussi aux trois tuiles déplaçables) ;
  • la case en direction de mouvement est occupé et la tuile qui l’occupe ne peut pas être déplacée – les règles d’addition des tuiles sont appliquées pour les cases compatibles.

À chaque action de l’utilisateur, les tuiles ne se déplacent qu’à une case voisine même si plusieurs cases dans la direction de mouvement sont vides. L’addition de tuiles se fait après quand le mouvement est impossible à cause d’une bordure de tableau ou d’une tuile incompatible :

  • les deux tuiles de valeur “1” et “2” sont compatibles et sont remplacées par une tuile de valeur “3” ;
  • les deux tuiles d’une valeur identique et supérieure à “3” sont remplacées par une tuile ayant le double de valeur (6, 12, 24, 48, 96, etc.) ;
  • les autres tuiles ne sont pas compatibles.

La tuile la plus avancée en direction du mouvement, par exemple la tuile la plus à gauche en cas de mouvement à gauche, est remplacé par une nouvelle tuile avec une valeur supérieure, l’autre tuile est supprimée laissant la place au mouvement de l’éventuelle tuile suivante. Par exemple, la suite 3-3-3-vide devient 6-3-vide-vide, la suite 3-3-3-3 devient 6-3-3-vide. Après le déplacement et l’addition, une nouvelle tuile de valeur “1” ou “2” aparraît dans l’une des cases vides de tableau dans la ligne ou la colonne opposée à la direction de déplacement. Par exemple, dans la colonne la plus à droite après le mouvement à gauche.

Le jeu est perdu quand aucun mouvement ni addition n’est plus possible. Le score est calculé comme la somme des toutes les valeurs de tuiles présentes sur le tableau au moment de la fin de jeu.

Version de base

La version simplifiée contient :

  • l’interface basée sur les composants standard Swing (par exemple les JLabel pour désigner la valeur d’une tuile), les layouts et le moteur du jeu;
  • l’interaction à l’aide du clavier et de la souris;
  • l’écran du début de jeu avec un bouton “commencer”;
  • l’écran de la fin de jeu avec le score et le bouton “relancer”.

Cette version doit obligatoirement être rendue, même si certains fonctionnalités sont absents.

Version avancée

La version avancée continent :

  • l’interface basée sur le dessin 2D (utilisation de classes Java2D pour le tableau et les tuiles);
  • l’animation de déplacement de tuiles et de leur addition;
  • le mouvement initié à partir d’un menu circulaire;
  • l’écran de meilleurs scores.

Vous devrez présenter cette version pendant la soutenance.

Fonctionnalités interactives

  • initier le mouvement des tuiles en appuyant sur les “flèches” du clavier ;
  • imitation d’un geste “swipe” avec la souris : l’utilisateur appuie sur le bouton, déplace la souris dans la direction souhaitée et relâche le bouton ;
  • menu circulaire apparaît en réponse au clique droit de la souris, un clique gauche sur le menu démarre le mouvement ;
  • marking menu : l’appui prolongé du bouton gauche de la souris sans mouvement fait apparaître le menu circulaire où la sélection d’option se fait par le mouvement dans la direction souhaitée, à intégrer avec le geste swipe.

Rendus

  • Code de la version basée sur le composants standard – au plus tard 20h00, jeudi 19 mai.
  • Code de la version finale basée sur le dessin 2D – au plus tard 18h00, mardi 24 mai.

Le code doit être envoyé par mail aux deux chargés des TP en mettant “[et3ihm] Rendu 1(2) Nom Prénom”. Vous allez recevoir une confirmation de réception une fois la date limite passée.

Note : Lors de la soutenance il vous sera demandé de montrer les deux versions avec le même code. Il doit donc être possible de choisir l’interface graphique voulu depuis votre application. Pensez à bien séparer la logique du jeu de sa représentation graphique.

Notation

  • premier rendu – 6 points
  • fonctionnalités de la version de base (au moment de la soutenance) – 4 points
  • fonctionnalités de la version avancée – 10 points.

Foire aux questions

Mon programme n’affiche rien, que faire ?

Mon programme compile sans erreur, mais n’affiche qu’une fenêtre vide.

Le simple fait de compiler sans erreur ne suffit pas à vérifier qu’il n’y a pas d’erreur sémantique telle qu’une référence nulle est passée à une fonction. Vérifiez la sortie que votre programme a faite dans la ligne de commande (“Console” en Eclipse). Souvent, vous y trouverez un message d’erreur tel que “NullPointerException” et une liste des appels des fonctions. Trouvez la première fonction dans cette liste qui est définie dans votre code en utilisant le nom de fichier et le numéro de la ligne problématique. Commencez votre mise à point dès cette ligne.

Je n’ai pas de message dans la ligne de commande, mais le programme n’affiche toujours rien.

Vérifiez que vous avez rajouté vos éléments de l’interface au panel de contenu de la fenêtre accessible via la fonction JFrame.getContentPane. Vous ne pouvez pas mettre les éléments graphiques directement dans la fenêtre sans passer par contentPane. Par contre vous pouvez le remplacer par un autre et unique élément.

Quelle est la différence entre AWT et Swing?

Pourquoi certaines fonctions accèptent Container au lieu de JPanel ? Qulle est la différence entre Frame et JFrame ?

AWT (Abstract Windowing Toolkit) est un ensemble de classes Java présent depuis les versions très anciennces du langage qui fournit une interface commune aux systèmes de fenêtrage. Ces classes permettent d’utiliser les fenêtres et les widgets natifs du système d’exploitation à travers les mêmes méthodes. Swing est un ensemble des classes écrit en Java fournissant plusieurs widgets standard sans avoir recours aux ceux du système d’expoitation. Il ne depend pas des particularités du système bien que, souvent, il soit plus lent à l’exécution. Pour ce faire, il duplique la fonctionnalité présente dans le système. Afin que cette dernière reste accéssible, les classes Swing sont différentes de celles de AWT. Le plupart des classes Swing commence par la lettre J. Vous êtes encouragés d’utiliser Swing dans vos exercices. Mélanger les classes Swing et AWT dans la même interface peut avoir des conséquence imprévisible puisque le système d’exploitation traite les widgets Swing comme des image alors que ceux de AWT sont les “vrais” widgets.