La boîte à Tutoriels de Christopher PECAUD

Top

Conception d'une IHM avec Java

Laisser un commentaire

SOMMAIRE

I Introduction
II Description générale de l'application
III Les aspects de l'interface graphique en détails
IV Les différentes boîtes de dialogue
V Boîte de création d'un nouveau fichier image
VI La boîte de dialogue palette
VII La gestion des événements

I Introducton

Dans ce premier tutoriel réservé à la conception d'une interface graphique , je vais vous donner les bases nécessaires afin de réaliser une interface graphique, qui pourra être utilisé dans le prochain projet, c'est-à-dire l'utilisation de bibiothèques de fonctions permettant de traiter des images graphiques. Nous allons donc dans ce premier tutoriel expliquer les différents objets importants qui constituent l’interface de notre application.

II Description générale de l'application

Dans cette partie nous allons voir en détail les principaux points importants qui constituent l’architecture de l’application. Nous avons voulu que notre application puisse ouvrir plusieurs fenêtres au sein du même environnement, nous avons donc réalisé une interface MDI(Multiple Documents Interface). Pour réaliser ce type d’interface il faut utiliser un type de Panel particulier qui est le JdesktopPane. En ce qui concerne les fenêtres filles il s’agit d’utiliser un type d’objet spécifique qui est une JInternalFrame. Si l’on regarde un peu plus près l’application on remarque que nous nous sommes efforcé de réaliser une interface standard contenant la plupart des objets que l’on retrouve actuellement, c’est-à-dire : Une barre de menus qui contient toutes les actions que l’application est capable de réaliser.

Deux barres d’outils :
1. Une permettant d’avoir accès aux fonctions les plus importantes à réaliser comme l’ouverture d’un fichier image déjà existant, ou la création d’un nouveau document image.
2. Une autre permettant d’avoir accès à plusieurs outils de dessin.

La couleur sélectionnée est utilisée pour le tracé des figures comme le rectangle ou l’ellipse par exemple. Comme vous pouvez le constater la palette des niveaux de gris est constituée d’un Jslider, permettant de sélectionné le niveaux de gris que l’on souhaite. La couleur ainsi sélectionnée se retrouve dans un JLabel. Pour réaliser cette palette nous avons créer une nouvelle fenêtre fille c’est-à-dire du type JInternalFrame.

III Les aspects de l'interface graphique en détails

1.La barre de menu

En ce qui concerne la barre de menus, nous avons regroupé des fonctions par groupe :

1.Fichier ;
2.Voir ;
3.Outils.

En ce qui concerne le premier groupe, le menu Fichier, on peut dire qu’il regroupe les principales commandes servant à gérer l’ouverture ou la création d’un fichier image de type gif ou jpeg. Il contient aussi une commande permettant de quitter l’application

Image montrant le menu de l'application

Concernant le deuxième groupe de commandes il est utilisé pour faire apparaître des objets utilitaires qui vont permettre de travailler sur les images, en l’occurrence il s’agit de la palette de couleur et de l’histogramme.

Ces deux objets seront étudiées dans cette partie mais plus bas.

Voici l’aspect de ce groupe de commandes de menu :

image montrant les commandes du menu voir

Un dernier groupe de commandes est utilisé pour mettre en œuvre les opérations de traitements des images. Les commandes sont Seuillage et Histogramme.

image montrant les commandes du menu outils

La première commande va permettre de réaliser la binarisation d’une image par l’intermédiaire d’un seul seuil ou de deux seuils. La commande Histogramme permet d’agir sur l’histogramme d’une image afin de soit :

  • 1.L’égaliser ;
  • 2.Soit de le normaliser.

Maintenant que nous avons vu en détail l’aspect de notre barre de menu nous allons voir comment nous avons fait pour implémenter la barre de menu. Pour introduire une barre de menu dans une application il faut tout d’abord créer une instance de l’objet JmenuBar de cette façon :

JmenuBar mnuBar = new JmenuBar() ;

Une fois que l’on a créé cet objet il faut créer les éléments qui vont composer cette barre de menu:

JMenu mnuFichier = new JMenu("Fichier") ;

Comme on peut le voir une commande de menu est créée par l’intermédiaire de l’objet JMenu. Maintenant que nous avons créé notre groupe de menus, on va pouvoir lui adjoindre une commande de menu de la façon suivante :

JMenuItem mnuOuvrir = new JMenuItem("Ouvrir") ;

Nous savons donc maintenant comment nous avons procéder pour réaliser notre barre de menus. Nous allons maintenant énoncer comment réaliser une barre d’outils en étudiant les deux barres que nous avons inclus dans notre application.

2. Les barres d’outils

L’interface que nous avons réalisé est composée de deux barres d’outils :
Une barre d’outils permettant de retrouver plus facilement les commandes importantes que l’on peut trouver dans la barre de menu que l’on vient juste de voir.
Une autre permettant de réaliser des tracés de figures géométriques sur une image que l’on a créée ou sur une image que l’on a chargé.

En java on peut créer différents types de barres d’outils variant principalement par leur orientation : verticale ou horizontale. Une barre d’outils peut être aussi encrable ou non c’est-à-dire que l’on a la possibilité de la bouger.
Pour pouvoir réaliser une barre d’outils on doit instancier un objet JToolbar :

JToolbar tlbAppli = new JToolbar();

Une fois créer il est possible de lui associer des boutons outils de la façon suivante :

JtoolButton btnOuvrir = new JtoolButton() ;

Pour associer le bouton à la barre d’outils il faut utiliser la méthode add :

TlbAppli.add(btnOuvrir) ;

Maintenant que nous avons détaillé les principaux points clés de l’application nous allons nous intéresser à la création des fenêtres filles dans une application MDI.

IV Les différentes boîtes de dialogue

La boîte de dialogue d’ouverture de fichier image jpeg ou gif.

image montrant la boîte de dialogue d'ouverture de fichiers image

Cette boîte de dialogue nous permet de sélectionné un fichier qui sera ensuite affiché dans une fenêtre fille. L’utilisateur sélectionne un fichier et valide sa sélection en cliquant sur le bouton Open.

Le nom de fichier apparaît dans la liste d’édition. L’utilisateur peut choisir aussi son type de fichier à charger.

Pour instancier ce type de boîte de dialogue, il faut utiliser le code suivant :

JFileChooser dlgOuvrirFichier = new JFileChooser(); 

Ensuite il est possible de la paramétrer pour pouvoir choisir le mode de sélection, dans notre cas ce paramètre doit nous permettre de sélectionner seulement des fichiers et donc on a besoin de la constante FILES_ONLY.

dlgOuvrirFichier.setFileSelectionMode(JFileChooser.FILES_ONLY);


Ensuite il faut rendre la boîte de dialogue active et visible, cette opération est réalisée avec la ligne suivante :

int resultat = dlgOuvrirFichier.showOpenDialog(this);

Ensuite il faut valider la sélection en testant si l’utilisateur a réalisé une sélection.

Pour finir le nom du fichier image sélectionné est ensuite mis dans la variable fichier qui est de type string. Une fois cette opération terminée on aura donc en mémoire le nom du fichier pour pouvoir ensuite afficher l’image correspondante.

if (resultat == JFileChooser.CANCEL_OPTION)
  fichier = null;
else{
  fichier = dlgOuvrirFichier.getSelectedFile();			
}.	  

V Boîte de création d'un nouveau fichier image

Cette boîte de dialogue nous permet de créer une nouvelle image en niveaux de gris. Cette boîte de dialogue permet de définir les dimensions de l’image que l’on souhaite créer. En effet l’utilisateur va pouvoir entrer, dans les deux champs réservés au texte, la hauteur ainsi que la largeur de l’image. Ces informations sont ensuite validées lorsque l’utilisateur appuie sur le bouton OK. Pour réaliser cette boîte de dialogue nous avons utilisé le GridLayout comme LayoutManager. Pour ajouter des zones de textes dans un container on instancie un objet de type JtextField.

JTextField txtHauteurImg ;
txtHauteurImg = new JTextField("0");
txtHauteurImg.addFocusListener(this); 

Comme on peut le voir la boîte de dialogue que nous avons construit possède aussi des « étiquettes ». Pour gérer la perte de focus d’un composant il existe une interface qui gère ce type d’événement et qui s’appelle FocusListener.

Pour l’utiliser on doit l’implémenter avec la classe qui va l’utiliser, c’est-à-dire dans notre cas La classe qui permet de créer notre boîte de dialogue de collecte des informations de notre future image.

id FenetreNouveauDocInfo extends JInternalFrame implements FocusListener

Comme nous pouvons le voir sur la partie de code suivante, on va surcharger seulement la méthode FocusLost de l’interface FocusListener.

public void focusLost(FocusEvent evt) {
update();
}

public void focusGained(FocusEvent evt) { }

void update() {
varHauteur = Integer.parseInt(txtHauteurImg.getText());
varLargeur = Integer.parseInt(txtLargeurImg.getText());
}

Comme cela lorsque l’on va cliquer sur le bouton OK de la boîte de dialogue, les informations varHauteur et varLargeur vont être mémoriser dans deux variables statiques qui pourront être utiliser par d’autres classes. Pour créer une étiquette on instancie la classe JLabel de cette façon :

JLabel lblHauteurImg = new JLabel("Hauteur : ");

Le constructeur de la classe prend en paramètre la légende qui sera affichée à l’écran par l’intermédiaire de l’étiquette.
La boîte de dialogue possède aussi deux boutons :
Le bouton OK qui permet de valider les informations que l’on vient de rentrer et permet la création de la nouvelle image.
Le bouton Annuler qui permet de quitter cette boîte de dialogue sans mémoriser les informations que l’on a saisi.

Pour créer un bouton dans un container il suffit d’instancier la classe Jbutton de la manière suivante :

	
JButton cmdOK = new JButton("OK");
JButton cmdAnnuler = new JButton("Annuler"); 

Le constructeur de la classe Jbutton prend en argument le nom du bouton qui sera affichée à l’intérieur du bouton.

VI La boîte de dialogue palette

image montrant la pallette de couleurs utilsée dans l'application

Comme toute application relative au dessin nous avons pensé qu’il serait utile de créer une boîte de dialogue Palette permettant de sélectionner un niveau de gris. Celle ci permet de dessiner des formes géométriques simples avec la couleur choisie par la glissière (Jslider).
Si l’on regarde bien la palette on s’aperçoit qu’elle est constituée des éléments suivants :
Une glissière permettant de sélectionner un niveau de gris.
Une barre de couleur permettant d’afficher les niveaux de gris de 0 à 255.
Un label permettant de visualiser la couleur que l’on a sélectionné.

Nous allons nous intéressé maintenant au code permettant la création d’un objet de type Jslider. La création s’effectue par l’intermédiaire du constructeur de la classe Jslider :

			
JSlider sldNvGris;
sldNvGris = new JSlider(0, 255); 

Le constructeur de la classe Jslider prend en argument la valeur minimale et la valeur maximale que l’on peut atteindre, en déplaçant la glissière. Si l’on veut positionner la glissière à sa création il suffit d’appeler la méthode setValue et de lui donner en argument la valeur à laquelle on souhaite positionner le curseur de la glissière. Par défaut la valeur de début est placée à la valeur 50. Pour pouvoir sélectionner une valeur par l’intermédiaire du curseur de la glissière, on est obligé d’implémenter l’interface ChangeListener .

En ce qui concerne la barre de niveaux de gris nous avons créer un objet de type Jpanel Et nous avons réécris sa méthode paint comme suit :

id PanelPalette extends JPanel {
int i;
Graphics ecran;
PanelPalette() {
  super();
  setBackground(new Color(150, 150, 150));
}

public void paint(Graphics g) {
for(i = 0; i < 256; i++) {
   g.setColor(new Color(i, i, i));
   g.drawLine(5 + i, 0, 5 + i, 15);
   }
}
}	

Nous pouvons dire que lorsque l’on dessine dans un objet par l’intermédiaire de sa méthode paint, nous sommes obligé de passer par un contexte de périphérique de type Graphics. Pour dessiner la bande de niveaux de gris nous avons introduit une boucle dans laquelle nous faisons varier l’indice i de 0 à 255. On incrémente ainsi à chaque fois le niveau de gris et on trace une barre verticale. Le résultat final est la barre de couleur que l’on voit sur la boîte de dialogue.

En ce qui concerne le résultat de l’affichage de la valeur de niveau de gris qu’on a sélectionné, on utilise un objet de type JPanel.

pnlCouleurContour.setBackground(new Color(Palette.nvGrisCouleurContour, 
                                Palette.nvGrisCouleurContour, 
                                Palette.nvGrisCouleurContour));

Si l’on regarde cette ligne de plus près on s’aperçoit que l’on utilise la méthode setBackground de la classe JPanel qui permet d’associer une couleur sur toute la totalité du panel.

Pour créer une nouvelle couleur on instancie un objet de type Color. En appelant le constructeur de la classe Color on lui donne en paramètres les trois composantes RVB, pour rouge, vert, bleu. Dans le cas d’un niveau de gris les trois composantes ont la même valeur.

VII La gestion des événements

La gestion des événements est très importante dans une interface. En effet elle va permettre à l’utilisateur de communiquer avec l’ordinateur pour lui donner des ordres.

Premièrement nous avons surtout eu besoin du gestionnaire qui permet de gérer l’appui sur une commande de menu. Pour ce faire on utilise un ActionListener avec ActionAdapter.

Par exemple on aura :

	
mnuOuvrir.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    System.out.println("commande Ouvrir sélectionnée");
    ouvrirFichier();
    FenetreInterne fenInterne = new FenetreInterne(fichier.toString());
				     
    System.out.println("Affichage Image");
				
    try {
      fenInterne.setSelected(true);
      System.out.println("Creation");
    }
    catch(PropertyVetoException pve) {
      System.out.println("Fenetre non sélectionnee");
    }
    System.out.println("Chargement terminee");		
  }
});

Ce code permet de réagir à la sélection, par l’intermédiaire du pointeur de la souris. Ce type d’événements est utilisé pour les commandes du menu et pour la gestion de l’appui sur les boutons, que ce soit les boutons de la barre d’outils ou ceux de validation dans les boîtes de dialogue.

Un autre type de gestion d’événement est très important pour notre application, c’est-à-dire ceux qui permet de gérer la souris. Ces événements vont nous permettre par exemple de réaliser les dessins lors de la création d’une image ou même sur une image que l’on vient de charger.

Pour ce faire nous avons implémenté les écouteurs d’événements MouseListener et MouseMotionListener . Mais nous avons juste besoin de gérer les événements :

L’appui sur un des boutons de la souris pour commencer le tracé d’une figure géométrique.


L’événement permettant de bouger le curseur de la souris.

Mais en utilisant la méthode d’implémentation de ces interfaces on est obligé de réécrire toutes les méthodes appartenant à celles-ci. Les seules fonctions que nous avons surchargées sont celles qui permettent de gérer les événements que nous venons de mettre en évidence. Ces fonctions sont :

MousePressed qui va nous permettre de déterminer les coordonnées de début de notre tracé de figure.

X_debut = e.getX();
Y_debut = e.getY();	  

MouseDragged qui nous permet de gérer le déplacement de la souris. Cela va nous permettre d’augmenter les coordonnées de fin de tracé.

X_current = e.getX();
Y_current = e.getY(); 

MouseReleased qui va nous permettre de valider la figure géométrique et de l’afficher sur l’image en respectant bien les coordonnées.

X_fin = e.getX();
Y_fin = e.getY();

Comme nous pouvons le constater on peut avoir à chaque fois que l’on utilise la souris ces coordonnées à l’écran. Les deux types d’événements que l’on vient de voir sont les plus utilisées, mais il reste encore à détailler les événements qui gèrent les fenêtres, et dans notre cas nous avons eu le plus besoin de celui permettant de quitter l’application, c’est-à-dire de fermer l’application principale.

addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent e) {
  System.exit(0);
  }
});	  	

Pour les fenêtre filles on dispose d’une autre classe d’écouteurs c’est-à-dire les InternalFrameListener.

	
addInternalFrameListener( new InternalFrameAdapter() {
  public void internalFrameClosing(InternalFrameEvent e) {
  dispose();
  }
});

Ce qui est intéressant quand on utilise des Adapter, c’est que l’on n’est pas obligé de réécrire toutes les méthodes implémentées dans leurs Listener. La méthode dispose permet simplement de fermer une fenêtre interne. Maintenant que nous avons vu en détail ce qui composait notre application, nous allons nous pencher sur des détails un peu plus techniques c’est-à-dire les traitements mis en œuvre.