Construction d`interface graphique

publicité
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Construction d'interface graphique
et programmation événementielle avec Java
Une interface graphique (composée de composants graphiques) ne sert à rien si elle ne permet
pas de réagir aux actions de l'utilisateur (clic sur un bouton, choix dans une liste, saisie au
clavier,…).
La conception d'une application avec interface graphique comprend donc deux étapes :
- mettre en place les composants graphiques (dessiner l'interface)
- permettre à l'interface graphique de réagir aux actions de l'utilisateur (coder le
dialogue entre l'utilisateur et l'application par l'intermédiaire des événements)
Les composants AWT et le dessin d'une interface graphique
Nous allons étudier comment créer une interface graphique grâce aux classes du package
AWT. (Il existe un package plus récent et plus complet appelé Swing, basé sur AWT.)
Tous les composants (contrôles) d'une interface graphique y compris la fenêtre principale de
l'application, héritent de la super-classe abstraite Component. Cette classe est donc l'ancêtre
de toute une hiérarchie de classes spécialisées dans la construction et le traitement des
éléments de l'interface graphique.
hiérarchie de classe des
composants AWT.
Button
Label
List
Checkbox
CheckboxGroup
Scrollbar
Canvas
TextField
Choice
Component
{abstraite}
TextComponent
TextArea
Container
{abstraite}
Panel
Applet
Frame
Window
Dialog
hérite de
1
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Description succincte des composants
•
•
•
•
•
•
•
•
•
•
Button : classe des boutons à cliquer
Canvas : objet zone de dessin
Checkbox : boîte à cocher
CheckboxGroup : regroupe plusieurs composants Checkbox, et réalise un ensemble de
boutons radio.
Choice : composant qui permet de gérer une liste déroulante (comme les ComboBox)
Label : affiche simplement une ligne de texte (étiquette)
List : composant spécialisé dans l'affichage d'une liste d'items
Scrollbar : pour choisir une valeur dans un intervalle.
TextComponent : permet d'éditer du texte. Rarement instancié directement
o TextField : une simple ligne d'édition.
o TextArea : zone d'édition de texte de plusieurs lignes, munie de barres de
défilement.
Container : (conteneur) classe abstraite qui sert de support à d'autres composants (y
compris à d'autres conteneurs). principales méthodes : add(), remove()
o Panel : c'est un conteneur simple, souvent placé dans un Frame.
Applet : c'est le conteneur des applets
o Window : fenêtre d'application sans bordure, ni barre de menus; c'est un
conteneur, géré par défaut par un BorderLayout.
Rarement instanciée directement, on utilise ses sous-classes Dialog et Frame.
Dialog : boîte de dialogue, qui dépend d'une fenêtre Frame, aussi
conteneur
Frame : fenêtre encadrée affichable, redimensionnable : c'est la fenêtre
typique d'une application graphique Java
Pour plus d'informations, utilisez la documentation de Java dans le répertoire
Construction et dessin des composants
Pour construire un composant en mémoire, il suffit d'appeler un de ses constructeurs:
Ex:
Button b = new Button("Cliquez moi !");
Label la = new Label ("Je suis une étiquette");
Checkbox cb = new Checkbox ("boite à cocher", true);
Construire un composant en mémoire, c'est lui réserver une zone en mémoire, mais ce n'est
pas tracer son graphique. Une fois le composant construit, il faut le dessiner dans un
conteneur (objet dérivé de Container). Pour cela, on appelle la méthode add( ) définie dans la
classe Container.
ex: Supposons qu'il existe un conteneur appelé fenetre (par exemple un Frame). Pour dessiner
les trois composants définis ci-dessus dans le conteneur fenetre, on écrit:
fenetre.add(b);
fenetre.add(la);
fenetre.add(cb);
2
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Création d'une interface graphique avec Java
Une application Java est composée de plusieurs classes qui collaborent entre elles pour réaliser
différents traitements en fonction des actions de l'utilisateurs ou d'événements internes.
Plusieurs sortes de classes entrent en composition d'une application complète :
- des classes techniques, prédéfinies dans le langage Java, comme les classes Vector, System,
NumberFormat, …
- des classes "métier", qui implémentent les objets réalisant les traitements spécifiques de
l'application (c'est le cœur de l'application).
- des classes graphiques, qui permettent le dialogue entre l'utilisateur et l'application
Le programmeur aura donc au moins deux types de classes à écrire : les classes "métier" et au moins
une classe graphique représentant la fenêtre de l'application. Intéressons nous à l'écriture de cette
classe.
Pour pouvoir utiliser les composants graphiques de java, il faut importer le package awt qui
contient les classes de ces composants:
import java.awt.*;
Ensuite, il convient de définir la classe qui va contenir l'interface graphique de l'application.
Cette classe doit hériter d'un conteneur :
- pour une application : Window ou le plus souvent Frame
- pour une applet : Applet (qui dérive de Panel)
class MonInterface extends Frame
{
/*Les composants qui s'insèrent dans la fenêtre principale sont déclarés comme des attributs
de cette classe (attention, à ce niveau, ils ne sont pas construits).*/
Label la;
TextField tf;
Button b;
List li;
/*Il faut évidemment définir un constructeur pour la classe MonInterface. Ce constructeur fait
appel au constructeur de sa classe mère Frame.*/
public MonInterface(String titre)
{
super(titre);
//appel au constructeur de Frame qui prend pour paramètre un titre
/*C'est dans le constructeur de la fenêtre principale que les composants qui lui
appartiennent sont construits …*/
la = new Label ("Voici une étiquette");
b = new Button ("Cliquez ici");
tf = new TextField(30); //largeur de 30 caractères
li = new List( );
li.add("Titi");
li.add("Toto");
li.add("Tutu");
3
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
/* Il faut ensuite définir les dimensions de la fenêtre avec la méthode setBounds qui
prend pour paramètre les coordonnées du coin supérieur gauche puis les dimensions
en pixels*/
this.setBounds(200, 100, 300, 300);
/* avant de dessiner des composants dans un conteneur, il faut définir comment on va
disposer ces composants dans le conteneur. On utilise pour cela un objet gestionnaire de
mise en forme (type LayoutManager) associé au conteneur. Nous choisissons la disposition
de gauche à droite qui est celle des gestionnaires FlowLayout */
FlowLayout disposition = new FlowLayout ( ); //construction du gestionnaire de mise en forme
this.setLayout(disposition); // On applique ce gestionnaire à la fenêtre MonInterface
/* Une fois le gestionnaire de mise en forme défini, on peut dessiner les composants à
l'intérieur de la fenêtre avec la méthode add( )*/
this.add(la);
this.add(b);
add(tf);
add(li);
}
} //fin de la classe graphique
/*Pour pouvoir exécuter l'application avec interface graphique, il faut créer une classe
principale, avec la méthode public static void main(…) qui va construire un objet de classe
MonInterface et l'afficher.*/
class MonApplication
{
public static void main(String[ ] args )
{
/* appel au constructeur de MonInterface */
MonInterface gui = new MonInterface("Première application graphique");
/* Par défaut, un Frame est invisible. Il faut donc l'afficher en appelant sa méthode
show( );*/
gui.show();
/*On peut définir le composant actif (celui qui aura le focus) avec la méthode
requestFocus( ) de la classe Component. Cette méthode est appliquée au composant qui
doit recevoir le focus. Attention, pour accéder à un objet qui est attribut d'un autre
objet, il faut le faire précéder du nom de l'objet contenant */
gui.tf.requestFocus( ); // le champ de texte tf de la fenêtre gui reçoit le focus
}//fin de la méthode principale
}
4
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Remarque :
L'interface graphique créée ainsi ne réagit pas aux actions de l'utilisateur : rien ne se
passe si on clique sur le bouton par exemple. C'est normal puisqu'on n'a pas associé de
traitement à la survenue d'événements. Nous allons voir cela dans la partie suivante.
Approfondissement: La mise en page des composants
A chaque objet de type Container (Frame, Applet, Panel, …) est associé un objet appelé
gestionnaire de mise en page (LayoutManager) qui se charge de gérer la disposition des
composants appartenant à ce conteneur.
Il existe plusieurs types de LayoutManager mais les présenter tous prendrait trop de temps et
ne serait pas très enrichissant. Nous avons un exemple avec FlowLayout, un gestionnaire qui
ajoute les composants les uns à la suite des autres, de gauche à droite et de haut en bas.
Reportez vous aux nombreux ouvrages traitant du sujet pour plus d'informations.
Il est possible de ne pas appliquer de LayoutManager : dans ce cas, il faut indiquer
explicitement qu'on n'applique pas le gestionnaire par défaut:
setLayout(null);
et ensuite il faut placer et dimensionner soit même les différents composants dans les
conteneurs avec la méthode setBounds(int x, int y, int largeur, int hauteur).
L'absence de LayoutManager permet un placement plus souple des composants au prix d'un
allongement du code (et d'une moindre portabilité des interfaces graphiques).
Exemple:
Voici le code d'une interface graphique de type Frame, qui ne comporte qu'un bouton et un
champ de texte. On n'utilise pas de LayoutManager.
class toto extends Frame
{
Button leBouton;
TextField leChamp;
public toto(String titre)
{
super(titre);
this.setLayout(null);
this.setBounds(200, 100, 300, 200);
leBouton = new Button("Cliquez ici");
leBouton.setBounds(50, 50, 100, 50);
leChamp = new TextField( );
leChamp.setBounds(50, 120, 200, 50);
this.add(leBouton);
this.add(leChamp);
}
}
5
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
public class essai
{
public static void main( )
{
toto montoto = new toto("Appli toto");
toto.show( );
toto.leBouton. requestFocus( );
}
}
Exercice
Le but de cet exercice est double :
- vous familiariser avec la création d'interface graphique en Java
- vous exercer à trouver les méthodes dont vous avez besoin en utilisant les fichiers de
documentation du jdk.
Créez une classe d'interface graphique pour permettre de choisir la couleur de la fenêtre
d'exécution avec des boutons radio.
Cette interface graphique sera composée des éléments suivants :
- d'une fenêtre avec un fond bleu, disposée environ au milieu de l'écran
- d'un Container de type Panel inséré dans la fenêtre. Ce Panel servira pour regrouper
les 3 cases à cocher. Il aura un fond blanc.
- de 3 cases à cocher qui serviront de boutons radio (il faudra utiliser des Checkbox et
un CheckboxGroup) insérés dans le Panel, qui permettront de choisir une couleur (par
exemple bleu, rouge, vert). Le bouton du bleu sera coché par défaut.
- d'un bouton avec pour légende "Quitter", centré en bas de la fenêtre, qui permettra de
fermer l'application.
Vous n'utiliserez pas de Layout pour la fenêtre et vous utiliserez le gestionnaire de mise en
page FlowLayout pour le Panel (c'est le gestionnaire par défaut).
Pour tester votre interface graphique, vous écrirez une classe principale (contenant la méthode
public static void main(String[ ] args).
Allure de l'interface à réaliser :
6
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Gestion des événements
Nous allons voir dans cette partie comment rendre dynamique une interface graphique, en
associant des traitements aux différentes événements utilisateur.
Principe : modèle abonnement/abonné
En Java, comme dans la plupart des langages, le mécanisme permettant le traitement
d'évènements repose sur le modèle abonnement/abonné.
Lorsque l'utilisateur effectue une action sur un composant graphique (clic de bouton,
modification d'un champ de texte, …) le composant graphique émet un événement. On dit
que c'est une source d'événement.
Cet événement est communiqué à un ou plusieurs objets qui veulent réagir à cet événement.
Par exemple, si l'événement changement d'option arrive, l'objet Frame réagit en changeant sa
couleur.
Pour qu'un d'événement soit communiqué à un objet, il faut que cet objet soit abonné au type
d'événement correspondant. En Java, un objet abonné est appelé "Listener" (écouteur en
français). L'écouteur réagit alors en exécutant une méthode spécifique appelée gestionnaire
d'événement en java (qui correspondent un peu aux procédures événementielles de VB).
Pour qu'un objet puisse être abonné à un événement, il faut absolument qu'il soit capable de
réagir à cet événement. Pour cela, il faut qu'il implémente toutes les méthodes qui permettent
de réagir aux différents événements possibles d'une certaine famille d'événements.
Toutes ces méthodes appartiennent à une interface, qui est une sorte de classe abstraite avec
seulement des méthodes abstraites. (cf encadré)
En résumé
Le composant qui est la cible d'une action de l'utilisateur (source d'événement) émet un
événement qu'il communique à un objet "écouteur" (abonné) qui réagit à l'événement en
exécutant une méthode appropriée, appelée gestionnaire d'événement.
Les 3 concepts principaux :
- Gestionnaire d'événement = méthode qui est appelée automatiquement lorsque un
événement écouté a lieu (cela correspond à peu près à la notion de procédure
événementielle en Visual basic)
- Ecouteur (Listener) = objet qui exécute les gestionnaires d'événement (les procédures
événementielles en quelque sorte). C'est souvent le conteneur des composants sources
d'événement. Cet objet "écoute" alors les événements en provenance des composants
source d'événement auquel il est abonné et réagit en exécutant le gestionnaire d'événement
associé.
- Composant source d'événements = composant qui avertit son (ses) écouteur(s) lorsqu'un
événement qui lui est destiné survient (ex: un bouton avertit la fenêtre principale lorsqu'on
lui clique dessus: c'est une source d'événement).
7
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Petit détour : Qu'est ce qu'une interface?
L'héritage multiple n'existe pas en Java : une classe fille ne peut dériver que d'une seule classe
mère (qui elle-même ne peut avoir qu'une seule mère, etc.). L'utilisation d'interfaces va
permettre de réaliser une certaine forme d'héritage multiple.
Une interface est une classe abstraite particulière dont tous les attributs sont constants et
dont toutes les méthodes sont abstraites (elles sont limitées à leur signature, elle n'ont pas de
corps).
Pour signifier qu'une classe hérite d'une interface on dit qu'elle implémente l'interface. On
utilise le mot clé implements au lieu de extends.
Lorsqu'une classe implémente une interface, elle doit obligatoirement redéfinir toutes les
méthodes de l'interface (leur attribuer du code). Si une méthode de l'interface ne sert pas, on
lui attribue alors un corps vide (écrire l'en-tête avec une paire d'accolades vides).
Une classe ne peut avoir qu'une seul classe mère (un seul extends) mais peut implémenter
plusieurs interfaces. Les interfaces permettent donc de réaliser une certaine forme d'héritage
multiple.
Codage nécessaire à la gestion des événements
3 parties de code sont nécessaires pour qu'un objet écouteur puisse réagir aux événements
voulus.
-
il faut que la classe de l'objet écouteur (souvent le conteneur des composants source
d'événement) implémente les interfaces correspondantes à la famille d'événements auquel
il va s'abonner
ex : class laFenetre extends Jframe implements ActionListener
{…
-
il faut que le composant source d'événement abonne l'objet écouteur (le mette dans la liste
des objets qu'il doit avertir) à ses événements
ex : Button b = new Button("Clic");
b.addActionListener(this) //le bouton b abonne son conteneur
-
il faut enfin que la classe de l'objet écouteur définisse (donne un corps à) toutes les
méthodes de l'interface qu'il implémente (codage des gestionnaires d'événement).
ex: public void ActionPerformed(actionEvent e)
{
//traitement qui doit s'effectuer au clic d'un bouton… }
Remarque : l'interface ActionListener ne possède qu'une seule méthode :
ActionPerformed
Petit exemple:
8
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
import java.awt.*;
import java.awt.event.*;
//attention il faut importer explicitement chaque sous-paquetage
class fenetre extends Frame implements ActionListener
{
Button b;
TextField texte;
public fenetre() //constructeur
{
super(); //construction d'un Frame
b = new Button("Cliquez ici"); //construction du bouton
b.addActionListener(this); //b abonne la fenetre à ses événements
texte = new TextField("Bouton pas encore cliqué :-( "); //construction du champ de texte
this.add(b, BorderLayout.SOUTH); //ajout des composants dans la fenetre
this.add(texte, BorderLayout.NORTH);
this.setBounds(200, 200, 200, 80); //définition de la position et de la taille
this.show();
}
public void actionPerformed(ActionEvent e) //gestionnaire de l'événement ActionEvent
{
texte.setText("Bouton cliqué! :-)");
}
}
class essai
//classe principale d'entrée dans le programme
{
public static void main(String args[])
{
fenetre f = new fenetre();
}
}
Les différentes familles d'événements
Il existe plusieurs famille d'événements qui dépendent de la nature des composants sources.
Par exemple, les Button, List, TextField envoient des événements de type Action. Ces
événements sont communiqués seulement aux objets abonnés qui implémentent l'interface
ActionListener. Un bouton qui doit abonner un objet implémentant ActionListener doit
appliquer la méthode addActionListener( ).
Les List, Choice et Checkbox envoient quant à eux des événements de type
ItemStateChanged. Seuls les objets qui implémentent l'interface ItemListener peuvent
s'abonner auprès de ces composants sources. Une liste ou une case à cocher qui doit abonner
un écouteur applique sa méthode addItemListener.
Les composants dérivés de Window (comme les Frame) génèrent plusieurs événements. A
chacun de ces événements correspond un gestionnaire d'événement (une méthode). Seuls les
objets qui implémentent l'interface WindowListener peuvent être abonnés à ces événements.
Pour chaque famille d'événement correspondant à une interface, il existe plusieurs
événements qui correspondent à un gestionnaire d'événement chacun.
9
S. Laporte
Interface graphique avec Java
Lycée Louise Michel BTS IG DA
Annexe : interfaces Listener du package java.awt.event :
•
•
•
•
•
•
•
•
•
•
•
ActionListener // clic, touche entrée, sélection d'un élément
Méthode : actionPerformed(actionEvent e)
Evénements générés par : AbstractButton, Button, List, MenuItem, TextField
abonnement par la méthode: addActionListener
AdjustementListener // déplacement du curseur d'une barre de défilement
Méthode : adjustmentValueChanged(AdjustmentEvent e)
Evénements générés par : Scrollbar
abonnement par la méthode: addAdjustementListener
ComponentListener // déplacement, affichage, masquage ou modification de taille des composants
Méthodes : componentHidden(ComponentEvent e)
componentMoved(ComponentEvent e)
componentResized(ComponentEvent e)
componentShown(ComponentEvent e)
Evénements générés par : Component (tous les composants)
abonnement par la méthode: addComponentListener
ContainerListener // ajout ou suppression d'un composant dans un conteneur
Méthodes : componentAdded(ContainerEvent e)
componentRemoved(ContainerEvent e)
Evénements générés par : Container (Pane, Applet, Window, Frame)
abonnement par la méthode: addContainerListener
FocusListener // obtention ou perte du focus par un composant
Méthodes : focusGained(FocusEvent e)
focusLost(FocusEvent e)
Evénements générés par : Component
abonnement par la méthode: addFocusListener
ItemListener // sélection dans une liste ou dans un groupe de cases à cocher
Méthodes : itemStateChanged(ItemEvent e)
Evénements générés par : Checkbox, CheckboxMenuItem, Choice, List
abonnement par la méthode: addItemListener
KeyListener // action sur une touche du clavier (pressée ou relachée)
Méthodes : keyPressed(KeyEvent e)
keyReleased(KeyEvent e)
keyTyped(KeyEvent e)
Evénements générés par : Component
abonnement par la méthode: addKeyListener
MouseListener // clic sur bouton, déplacement du pointeur
Méthodes : mouseClicked(MouseEvent e)
mouseEntered(MouseEvent e)
mouseExited(MouseEvent e)
mousePressed(MouseEvent e)
mouseReleased(MouseEvent e)
Evénements générés par : Component
abonnement par la méthode: addMouseListener
MouseMotionListener // événements de glisser-déplacé
Méthodes : mouseDragged(MouseEvent e)
mouseMoved(MouseEvent e)
Evénements générés par : Component
abonnement par la méthode: addMouseMotionListener
TextListener // modification du texte d'un composant texte
Méthodes : textValueChanged(TextEvent e)
Evénements générés par : TextComponent (TextField ou TextArea)
abonnement par la méthode: addTextListener
WindowListener // fenêtre activée, désactivée, réduite, fermée, ...
Méthodes : windowActivated(WindowEvent e)
windowClosed(WindowEvent e) //après la fermeture de la fenêtre
windowClosing(WindowEvent e) //au clic sur la croix en haut à droite de la barre de titre
windowDeactivated(WindowEvent e)
windowDeiconified(WindowEvent e)
windowIconified(WindowEvent e)
windowOpened(WindowEvent e)
Evénements générés par : Window (ou Frame)
abonnement par la méthode: addWindowListener
10
Téléchargement