Vous êtes sur la page 1sur 105

Interface

Homme/Machine
Graphical User Interface
IHM/GUI
BOUSETTA Ibrahim
Interface avec l’utilisateur
La quasi-totalité des programmes
informatiques nécessitent
l’affichage de questions posées à
l’utilisateur
l’entrée de données par l’utilisateur
l’affichage des résultats obtenus par le
traitement informatique
Cet échange d’informations peut
s’effectuer avec une interface utilisateur
(UI en anglais) en mode texte (ou
console) ou en mode graphique
ibbousetta@gmail.com BOUSETTA Ibrahim
Interface graphique
Une interface graphique est formée d’une
ou plusieurs fenêtres qui contiennent
divers composants graphiques (widgets)
tels que
Boutons
listes déroulantes
Menus
champ texte
etc.
Les interfaces graphiques sont souvent
appelés GUI d’après l’anglais Interface
ibbousetta@gmail.com BOUSETTA Ibrahim
Programmation conduite par les événements

Une interface graphique impose une façon


particulière de programmer
La programmation « conduite par les
événements » est du type suivant :
les actions de l’utilisateur (déplacement,
clic de souris, frappe de touche du
clavier,…) engendrent des événements
qui sont mis dans une file d’attente
le programme récupère un à un ces
événements et les traite
ibbousetta@gmail.com BOUSETTA Ibrahim
les écouteurs

Le JDK utilise une architecture de type «


observateur - observé » :
les composants graphiques (boutons,
listes, menus,…) sont les observés
chaque composant graphique a ses
observateurs (ou écouteurs, listeners)
qui s’enregistrent auprès de lui comme
écouteur d’un certain type d’événement
(par exemple, clic de souris)

ibbousetta@gmail.com BOUSETTA Ibrahim


Rôle d’un écouteur

Il est prévenu par le composant graphique


dès qu’un événement qui le concerne
survient sur ce composant
Il exécute alors l’action à effectuer en
réaction à l’événement
Par exemple, l’écouteur du bouton « Exit
» demande une confirmation à l’utilisateur
et termine l’application

ibbousetta@gmail.com BOUSETTA Ibrahim


Les API

2 bibliothèques :
AWT (Abstract Window Toolkit, JDK 1.1)
Swing (JDK 1.2)
Swing et AWT font partie de JFC (Java
Foundation Classes) qui offre des facilités
pour construire des interfaces graphiques
Swing est construit au-dessus de AWT
même gestion des événements
les classes de Swing héritent des
classes de AWT
ibbousetta@gmail.com BOUSETTA Ibrahim
Swing ou AWT ?

Tous les composants de AWT ont leur


équivalent dans Swing en plus
plus joli
avec plus de fonctionnalités que AWT
Mais Swing est lourd et plus lent
Swing offre de nombreux composants qui
n’existent pas dans AWT
⇒ Il est fortement conseillé d’utiliser les
composants Swing et ce cours sera donc
centré sur Swing
ibbousetta@gmail.com BOUSETTA Ibrahim
Paquetages principaux

AWT : java.awt et java.awt.event


Swing : javax.swing, javax.swing.event, et
des sous-paquetages de javax.swing dont les
principaux sont
liés à des composants ; table, tree, text (et
ses sous-paquetages), filechooser,
colorchooser
liés au look and feel général de l’interface (plaf
= pluggable look and feel) ; plaf, plaf.basic,
plaf.metal, plaf.windows, plaf.motif

ibbousetta@gmail.com BOUSETTA Ibrahim


Modèle de conception graphique
Les classes graphiques de Java sont très
nombreuses mais il existe trois principaux types
d'objets que l'on peut identifier facilement :
Component : Le composant peut être un bouton, une
liste, un champ de texte ou encore une case à
cocher.
Container : Le conteneur qui est un composant
contient d'autres composants. Il peut-être une fenêtre,
un panneau ou une boîte de dialogue.
Layout Manager : Le gestionnaire de contenu qui va
gérer la façon dont les composants sont placés dans
les conteneurs. Il existe plusieurs types de
gestionnaire de contenu BorderLayout , GridLayout,
…)
ibbousetta@gmail.com BOUSETTA Ibrahim
diagramme objet qui résume le
modèle

ibbousetta@gmail.com BOUSETTA Ibrahim


Structure multi-couches de
JFrame

ibbousetta@gmail.com BOUSETTA Ibrahim


Créer des objets JFrame

import javax.swing.*;

public class Ex1 {

public static void main ( String [] args ) {

JFrame myFrame = new JFrame("Titre de la fenêtre");

myFrame.setVisible(true); // Rend la fenêtre visible


myFrame.setSize(300,200); // Fixe la taille
}
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Créer des JFrame en tant qu'application

public class Ex2 extends JFrame {


// Constructeur
public Ex2(String titre) {
setTitle(titre);
setSize(300,200);
setVisible(true);
}
public static void main ( String [] args ) {
Ex2 myFrame = new Ex2("JFrame en tant
qu'application");
}
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Taille d’une fenêtre

pack() donne à la fenêtre la taille nécessaire


pour respecter les tailles préférées des
composants de la fenêtre (tout l’écran si cette
taille est supérieure à la taille de l’écran)
Taille ou un emplacement précis sur l’écran (en
pixels) :
setLocation(int xhg, int yhg) (ou Point en
paramètre)
setSize(int largeur, int hauteur) (ou
Dimension en paramètre)
setBounds(int x, int y, int largeur, int
hauteur) (ou Rectangle en paramètre)
ibbousetta@gmail.com BOUSETTA Ibrahim
Positionnement d’une fenêtre et
icône
importer java.awt.*;

public Fenetre() {

// Centrage de la fenêtre
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
int hauteurEcran = d.height;
int largeurEcran = d.width;
setSize(largeurEcran/2, hauteurEcran/2);
setLocation(largeurEcran/4, hauteurEcran/4);
// tant qu’on y est, ajoutons l’icône…
Image img = tk.getImage("icone.gif");
setIconImage(img); centre une fenêtre
sur l’écran
//. . . setLocationRelativeTo(null)
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Composants lourds

Pour afficher des fenêtres (instances de


JFrame), Java s’appuie sur les fenêtres
fournies par le système d’exploitation hôte dans
lequel tourne la JVM
Les composants Java qui, comme les JFrame,
s’appuient sur des composants du système hôte
sont dit « lourds »
L’utilisation de composants lourds améliore la
rapidité d'exécution mais nuit à la portabilité et
impose les fonctionnalités des composants

ibbousetta@gmail.com BOUSETTA Ibrahim


Composants légers

AWT utilise les widgets du système d’exploitation


pour tous les composants graphiques (fenêtres,
boutons, listes, menus,…)
Swing ne les utilise que pour les fenêtres de base
« top-level »
Les autres composants, dits légers, sont dessinés
par Swing dans ces containers lourds
Attention, les composants lourds s’affichent
toujours au-dessus des composants légers

ibbousetta@gmail.com BOUSETTA Ibrahim


Containers lourds

Il y a 3 sortes de containers lourds (un autre,


JWindow, est plus rarement utilisé) :
JFrame fenêtre pour les applications
JApplet pour les applets
JDialog pour les fenêtres de dialogue
Pour construire une interface graphique avec
Swing, il faut créer un (ou plusieurs) container
lourd et placer à l’intérieur les composants légers
qui forment l’interface graphique

ibbousetta@gmail.com BOUSETTA Ibrahim


Hiérarchie d’héritage des containers lourds

ibbousetta@gmail.com BOUSETTA Ibrahim


Classe JComponent

La plupart des widgets de Swing sont des


instances de sous-classes de la classe
Jcomponent
Les instances des sous-classes de JComponent
sont de composants « légers »
JComponent héritent de la classe Container
Tous les composants légers des sous-classes de
JComponent peuvent donc contenir d’autres
composants

ibbousetta@gmail.com BOUSETTA Ibrahim


Les Containers

Des composants sont destinés spécifiquement à


recevoir d’autres éléments graphiques :
les containers « top-level » lourds JFrame, JApplet,
JDialog, Jwindow
les containers « intermédiaires » légers JPanel,
JScrollPane, JSplitPane, JTabbedPane, Box (ce
dernier est léger mais n’hérite pas de JComponent)

ibbousetta@gmail.com BOUSETTA Ibrahim


JPanel

JPanel est la classe mère des containers


intermédiaires les plus simples
Un JPanel sert à regrouper des composants
dans une zone d'écran
Il n’a pas d’aspect visuel déterminé ; son aspect
visuel est donné par les composants qu’il contient
Il peut aussi servir de composant dans lequel on
peut dessiner ce que l’on veut, ou faire afficher
une image (par la méthode paintComponent)

ibbousetta@gmail.com BOUSETTA Ibrahim


Avant le JDK 5, il n’était pas possible d’ajouter
directement d’autres composants aux containers
« top-level »
Ces containers sont associés à un autre
container, le « content pane » dans lequel on
ajoute les composants
On obtient ce content pane par (topLevel est un
container lourd ; JFrame par exemple)
Container contentPane = topLevel.getContentPane();

ibbousetta@gmail.com BOUSETTA Ibrahim


Depuis JDK 5

On peut désormais ajouter directement les


composants dans un composant « top-level » :

frame.add(label, BorderLayout.NORTH);
frame.add(b1, BorderLayout.SOUTH);

Ce container va en fait déléguer à son content


pane (qui existe toujours dans le JDK 5)

ibbousetta@gmail.com BOUSETTA Ibrahim


Ajouter les composants

Le plus souvent on ajoute les composants dans le


constructeur (ou dans des méthodes appelées
par le constructeur) du composant « top-level » :

public Fenetre() {
...
Container cp = this.getContentPane();
JLabel label = new JLabel("Bonjour");
JButton b1 = new JButton("Cliquez moi !");
add(label, BorderLayout.NORTH);
add(b1, BorderLayout.SOUTH);
...
ibbousetta@gmail.com BOUSETTA Ibrahim
gestionnaire de contenu
(LayoutManager).

L’utilisateur peut changer la taille d’une fenêtre ;


les composants de la fenêtre doivent alors être
repositionnés
Les fenêtres (plus généralement les containers)
utilisent des gestionnaires de mise en place
(layout manager) pour repositionner leurs
composants
Il existe plusieurs types de layout managers avec
des algorithmes de placement différents

ibbousetta@gmail.com BOUSETTA Ibrahim


Indications de positionnement

Quand on ajoute un composant dans un


container on ne donne pas la position
exacte du composant
On donne plutôt des indications de
positionnement au gestionnaire de mise
en place
explicites (BorderLayout.NORTH)
ou implicites (ordre d’ajout dans le scontainer)

ibbousetta@gmail.com BOUSETTA Ibrahim


Algorithme de placement

Un layout manager place les composants


« au mieux » suivant
l’algorithme de placement qui lui est propre
les indications de positionnement des
composants
la taille du container
les tailles préférées des composants

ibbousetta@gmail.com BOUSETTA Ibrahim


Classe java.awt.Dimension

Cette classe est utilisée pour donner des


dimensions de composants en pixels
Elle possède 2 variables d’instance
publiques de type int
Height
Width
Constructeur : Dimension(int, int)

ibbousetta@gmail.com BOUSETTA Ibrahim


Tailles des composants

Tous les composants graphiques (classe


Component) ont plusieurs types de tailles
qui sont utilisées pour leur affichage
taille maximum
taille préférée
taille minimum
Accesseurs et modificateurs associés (classe
java.awt.Component) :
{get|set}{Maximum|Preferred|Minimum}Size

ibbousetta@gmail.com BOUSETTA Ibrahim


Taille préférée

La taille préférée est la plus utilisée par les layout


managers ; un composant peut l’indiquer en
redéfinissant la méthode « Dimension
getPreferredSize() »
On peut aussi l’imposer « de l’extérieur » avec la
méthode « void setPreferredSize(Dimension)
»
Mais le plus souvent, les gestionnaires de mise en
place ne tiendront pas compte des tailles
imposées de l’extérieur

ibbousetta@gmail.com BOUSETTA Ibrahim


Taille minimum

Quand un composant n’a plus la place pour être


affiché à sa taille préférée, il est affiché à sa taille
minimum sans passer par des tailles
intermédiaires
Si la taille minimum est très petite, ça n’est pas
du plus bel effet ; il est alors conseillé de fixer
une taille minimum, par exemple par
c.setMinimumSize(c.getPreferredSize());

ibbousetta@gmail.com BOUSETTA Ibrahim


Changer le Layout manager

Chaque type de container a un


gestionnaire de placement par défaut
On peut changer ce gestionnaire de
placement d’un Container par la
méthode setLayout(LayoutManager)
de la classe Container

ibbousetta@gmail.com BOUSETTA Ibrahim


Layout manager par défaut d’une
fenêtre

Le gestionnaire de mise en place par défaut des


fenêtres JFrame est du type BorderLayout
On peut changer ce gestionnaire de mise en place
en envoyant la méthode
setLayout(LayoutManager) de la classe
Container au content pane
Depuis le JDK 5 on peut utiliser directement la
méthode setLayout de la fenêtre (elle
délègue au content pane)

ibbousetta@gmail.com BOUSETTA Ibrahim


Types de Layout manager

Les types les plus courants de gestionnaire de mise


en place (dans java.awt) :
BorderLayout : placer aux 4 points cardinaux
FlowLayout : placer à la suite
GridLayout : placer dans une grille
GridBagLayout : placements complexes
BoxLayout : placer verticalement ou horizontalement
(dans javax.swing)
Un nouveau gestionnaire de mise en place a été introduit
par Java SE 6 (dans javax.swing) :
• GroupLayout : placer des groupes de composants en distinguant
le placement vertical et horizontal

ibbousetta@gmail.com BOUSETTA Ibrahim


Gestionnaire FlowLayout

Ce gestionnaire place les composants dans l'ordre dans lequel


ils sont ajoutés au conteneur. De plus, il organise l'espace en
lignes. Dès qu'une ligne est remplie, il en commence une autre.
Lorsque l'utilisateur redimensionne la fenêtre, les composants
se replacent dynamiquement.
De même, si vous ajoutez un bouton, le gestionnaire réagit
immédiatement

ibbousetta@gmail.com BOUSETTA Ibrahim


Gestionnaire FlowLayout

Code source :
JPanel panel = new JPanel(); // Le conteneur
panel.setLayout( new FlowLayout() );

Ou
FlowLayout lmanager = new FlowLayout();
getContenentPan().setLayout( lmanager );

ibbousetta@gmail.com BOUSETTA Ibrahim


Gestionnaire BorderLayout
l'utilisation du gestionnaire
BorderLayout permet de diviser
l'espace en 5 régions distinctes
Affiche au maximum 5
composants (aux 4 points
cardinaux et au centre)
Essaie de respecter la hauteur
préférée du nord et du sud et la
largeur préférée de l’est et de
l’ouest ; le centre occupe toute la
place restante
L'inconvénient de chaque région
est de ne pouvoir accueillir qu'un
seul composant.
Pour résoudre ce problème, il vous
suffit d'ajouter un JPanel à la
région concernée et d'y ajouter les
composants
ibbousetta@gmail.com BOUSETTA Ibrahim
Exemple de BorderLayout
public class TestLayout extends JFrame {
JButton b1= new JButton("nord"); JButton b12= new
JButton("nord2");
JButton b2= new JButton("sud"); JButton b3= new JButton("droit");
JButton b4= new JButton("centre"); JButton b5= new
JButton("gauche");
public TestLayout() {

setLayout(new BorderLayout());
JPanel jpn= new JPanel();
jpn.setLayout(new BorderLayout());
jpn.add(b1,BorderLayout.NORTH);
jpn.add(b12,BorderLayout.SOUTH);
getContentPane().add(jpn,BorderLayout.NORTH);
getContentPane().add(b2,BorderLayout.SOUTH);
getContentPane().add(b3,BorderLayout.EAST);
getContentPane().add(b4,BorderLayout.CENTER);
getContentPane().add(b5,BorderLayout.WEST);
}
….

}
ibbousetta@gmail.com BOUSETTA Ibrahim
Gestionnaire GridLayout
Ce gestionnaire organise les composants en lignes et
colonnes à l'instar d'un tableau.
Néanmoins, les cellules font toutes la même taille et si vous
souhaitez affecter des tailles différentes, mieux utiliser un
gestionnaire de type BoxLayout.
GridLayout()
Crée un gestionnaire GridLayout avec une colonne par
composant sur une seule ligne
GridLayout(int rows, int cols)
Crée un gestionnaire GridLayout avec cols colonnes et
rows lignes
GridLayout(int rows, int cols, int hgap, int vgap)
Crée un gestionnaire GridLayout avec cols colonnes et
rows lignes, un espacement vertical de vgap et un
espacement horizontal de hgap.
ibbousetta@gmail.com BOUSETTA Ibrahim
Container contentPane = getContentPane();
// Création d'un JPanel pour la région CENTER
centerPanel = new JPanel(new GridLayout(4,4) );
// Ajout du centerPanel au panneau principal
contentPane.add(centerPanel, BorderLayout.CENTER);
String cchaine = "789/456*123-0.=+";
for (int i=0;i<cchaine.length();i++)
{
btab[i] = new JButton( cchaine.substring(i,i+1) );
centerPanel.add(btab[i]);
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Gestionnaire BoxLayout

Ce gestionnaire permet de placer les composants sur une


seule ligne ou colonne.
En général, ce gestionnaire s'utilise avec le conteneur Box
mais il peut également être utilisé avec un JPanel.
D'ailleurs, le gestionnaire par défaut de l'objet Box est un
BoxLayout.
L'intérêt d'utiliser l'objet Box est qu'il contient un certain
nombre de méthodes statiques très utiles pour la gestion
des BoxLayout.
Les objets de type Box étant des conteneurs, ils s’utilisent
de la façon suivante :
Box b = Box.createHorizontalBox();

ibbousetta@gmail.com BOUSETTA Ibrahim


Boutons

ibbousetta@gmail.com BOUSETTA Ibrahim


Bouttons

Un bouton peut contenir du texte (qui


peut être du code HTML) mais aussi une
image (et on peut choisir la position
relative des 2)
Le caractère souligné du texte indique le
caractère mnémonique (pour simuler un
clic avec le clavier)
Un bouton peut être invalidé (texte en «
gris » du bouton de droite)

ibbousetta@gmail.com BOUSETTA Ibrahim


HTML dans les boutons

Les dernières versions de swing ont ajouté la


possibilité d’inclure du code HTML dans les labels
et les boutons (tous les types de boutons)

Il suffit pour cela d’inclure le texte dans les


balises <html> et </html> (en fait, seul le
<html> du début est indispensable) :

new JButton("<html>Ligne 1<p>Ligne 2</html>")

ibbousetta@gmail.com BOUSETTA Ibrahim


Code pour un bouton

JButton()
Crée un nouveau bouton sans texte ni icône
JButton(Action a)
Crée un bouton dont les propriétés sont issues de l’objet
Action fourni en paramètre. Les objets Action ou
ActionListener sont utiles pour la gestion des
évènements
JButton(Icon icon)
Crée un bouton avec l’icône spécifié
JButton(String text)
Crée un bouton avec le texte spécifié.
JButton(String text, Icon icon)
Crée un bouton avec le texte et l’icône spécifié

ibbousetta@gmail.com BOUSETTA Ibrahim


Code pour un bouton

JButton b1, b2, b3;


ImageIcon leftIcon = new
ImageIcon("images/right.gif");
b1 = new JButton("Invalider le bouton", leftIcon);
// Position par défaut : CENTER, RIGHT
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEFT);
b1.setMnemonic('I');
b1.setActionCommand("invalider");
...
b3.setEnabled(false);
getContentPan().add(b1);

ibbousetta@gmail.com BOUSETTA Ibrahim


Écouteur pour un bouton

L'intérêt d'un bouton est de pouvoir réaliser une


action lorsque l'on clique dessus. Ceci est
possible grâce aux évènements.
De manière générale, les évènements en Java
sont gérés par le principe de l'écouteur et de
l'objet écouté. Chaque objet capable de
provoquer un événement, doit être recensé
auprès de l'objet écouteur pour qu'une action soit
entreprise lors de l'appui sur le bouton.
En général, l'écouteur est un conteneur qui va
gérer les évènements de tous les composants
qu'il contient.

ibbousetta@gmail.com BOUSETTA Ibrahim


Écouteur pour un bouton

Public class TestJButton extends Jframe implements ActionListener {

…..

b1.addActionListener(this);
...
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("invalider")) {
b2.setEnabled(false);
b1.setEnabled(false);
b3.setEnabled(true);
}
else { . . . }
}

ibbousetta@gmail.com BOUSETTA Ibrahim


ToggleButton

Représente les boutons qui ont 2 états :


sélectionnés ou pas
On utilise plutôt ses 2 sous-classes
CheckBox : l’aspect visuel du bouton
change suivant son état
RadioButton : un seul bouton d’un groupe
de boutons radio (ButtonGroup) peut être
sélectionné à un moment donné

ibbousetta@gmail.com BOUSETTA Ibrahim


Boîte à cocher
: Traitement des événements

Un clic sur un ToggleButton génère un


ActionEvent et un ItemEvent
Avec une boîte à cocher, le plus simple est de
traiter les ItemEvent avec un ItemListener
Mais les boîtes à cocher n’ont souvent pas
d’écouteurs et on relève leur valeur quand on en
a besoin avec isSelected()

ibbousetta@gmail.com BOUSETTA Ibrahim


boîtes à cocher :ItemListener

class BoiteListener implements ItemListener {


public void itemStateChanged(ItemEvent e) {
Object source = e.getItemSelectable();
if (source == boite) {
if (e.getStateChange() ==
ItemEvent.DESELECTED)
...
}

ibbousetta@gmail.com BOUSETTA Ibrahim


boutons radios

ButtonGroup groupe = new ButtonGroup();


JRadioButton b1 = new JRadioButton("Choix 1");
JRadioButton b2 = new JRadioButton("Choix 2");
groupe.add(b1);
groupe.add(b2);
panel.add(b1);
panel.add(b2);

ibbousetta@gmail.com BOUSETTA Ibrahim


Bouton radio
Traitement des événements

Avec les boutons radio, le plus simple est


d’écouter avec un ActionListener
Cet événement est engendré quand le bouton
radio est sélectionné (pas quand il est
désélectionné)
L’utilisation d’un ItemListener serait plus
complexe car la sélection d’un bouton du groupe
désélectionne tous les autres et engendre donc
un grand nombre de ItemEvent

ibbousetta@gmail.com BOUSETTA Ibrahim


Entrées de texte

Composants « texte »
JLabel : texte non
modifiable par
l’utilisateur
JTextField : entrer une
seule ligne
JPasswordField : entrer
un mot de passe non
affiché sur l’écran
JTextArea : quelques
lignes de texte avec
une seule police de
caractères

ibbousetta@gmail.com BOUSETTA Ibrahim


JTextComponent
Contient les méthodes de base pour traiter
une zone de saisie ou/et d’affichage de
texte :
{get/set}Text pour obtenir ou mettre
le texte (ou une partie du texte)
contenu dans le composant
setEditable() pour indiquer si
l’utilisateur peut modifier le texte
copier/couper/coller avec le clipboard du
système
etc.
ibbousetta@gmail.com BOUSETTA Ibrahim
JTextField
Associé à un composant JLabel , JTextField
permet à l'utilisateur de saisir du texte. Voici un
exemple d'utilisation :
JTextField champ = new
JTextField("Saisissez votre texte",40);
Cet exemple construit un champ de texte de 40
colonnes. L'utilisateur peut saisir plus de 40
caractères, mais l'affichage sera limité à cette
valeur.
Pour changer le texte affiché, la méthode setText
de la superclasse va s'avérer utile.
La methode getText permettra de récupérer le
texte saisit par l’utilisateur.
ibbousetta@gmail.com BOUSETTA Ibrahim
JTextArea
JTextArea permet la saisie de texte sur plusieurs lignes. Il est
plus complexe et offre plus de possibilités que JTextField.
Il est très utilisé lorsqu'il s'agit de saisir une quantité
importante de texte. Il offre de nombreuses fonctionnalités
comme le retour à la ligne automatique.
Pour créer un objet de type JTextArea , de 40 colonnes et 8
lignes :
JTextArea zone = new JTextArea(8,40);
Pour autoriser le retour à la ligne automatique, on appelle la
méthode setLineWrap :
zone.setLineWrap(true);
setWrapStyleWord(boolean) pour que les mots ne soient
pas coupés en fin de ligne
Barres de défilement
JScrollPane scrollpane = new JScrollPane(champ);
panel.add(scrollpane);
ibbousetta@gmail.com BOUSETTA Ibrahim
JPasswordField

Pour des raisons de sécurité, un mot de passe ne


doit pas être visible lorsqu'on le tape.
Pour une sécurité accrue, ce composant ne
stocke pas son contenu dans une chaîne mais
dans un tableau de caractères.
JPasswordField pass = new JPasswordField(10);
pass.setEcho Char('#');
char [] tableau = pass.getPassword();
Les mots de passe doivent être récupérés dans
un tableau de char et pas dans une String pour
pouvoir les effacer de la mémoire après
utilisation

ibbousetta@gmail.com BOUSETTA Ibrahim


JFormattedTextField

Cette classe fille de JTextField a été


introduite par le SDK 1.4
Elle permet de donner un format pour la
saisie des données (et aussi
éventuellement pour leur affichage)
De très nombreuses possibilités sont
offertes au programmeur ; par exemple,
pour dire ce qui se passe si la valeur saisie
ne correspond pas au format

ibbousetta@gmail.com BOUSETTA Ibrahim


DateFormat f =
new SimpleDateFormat("dd/MM/yyyy");
DateFormatter df = new DateFormatter(f);
JFormattedTextField ftf =
new JFormattedTextField(df);
// Pour montrer le format de saisie
// à l’utilisateur
tft.setValue(new Date());

try { // # por nombre, * any thing, ? char


MaskFormatter mf =
new MaskFormatter("(##)## ## ## ##");
// Si on veut indiquer les emplacements
// à l’utilisateur :
mf.setPlaceholderCharacter(’_’);
JFormattedTextField ftf =
new JFormattedTextField(mf);
} catch(ParseException e) { . . . }

ibbousetta@gmail.com BOUSETTA Ibrahim


Généralités sur les dialogues

Une fenêtre de dialogue dépend d’une Jframe


Elle peut être modale (l’utilisateur doit répondre
avant de faire autre chose) ou non
JOptionPane est un composant léger, classe
fille de Jcomponent
elle permet d’avoir très simplement les cas les plus
fréquents de fenêtres de dialogue
elle affiche une fenêtre modale
Pour les cas non prévus par JOptionPane, on
doit utiliser la classe Jdialog (composant lourd)

ibbousetta@gmail.com BOUSETTA Ibrahim


Utilisation de JOptionPane

4 méthodes static de la classe qui font


afficher des fenêtres de dialogue modales de
divers types :
message d’information avec bouton OK
(showMessageDialog)
demande de confirmation avec boutons Oui, Non et
Cancel (showConfirmDialog)
saisie d’une information sous forme de texte, de choix
dans une liste ou dans une combobox
(showInputDialog)
fenêtres plus complexes car on peut configurer les
composants (showOptionDialog)
ibbousetta@gmail.com BOUSETTA Ibrahim
Look de la fenêtre de dialogue

Chaque type de fenêtre de dialogue a un aspect différent


Cet aspect est donné par
l’icône placée en haut à gauche de la fenêtre
les boutons placés en bas de la fenêtre
On peut indiquer un type de message qui indiquera l’icône
affichée en haut, à gauche de la fenêtre (message
d’information par défaut)
Ce type est spécifié par des constantes :
JOptionPane.INFORMATION_MESSAGE
JOptionPane.ERROR_MESSAGE
JOptionPane.WARNING_MESSAGE
JOptionPane.QUESTION_MESSAGE
JOptionPane.PLAIN_MESSAGE

ibbousetta@gmail.com BOUSETTA Ibrahim


Boutons placés dans la fenêtre

Ils dépendent des méthodes appelées :


showMessageDialog : bouton Ok
showInputDialog : Ok et Cancel
showConfirmDialog : dépend du paramètre passé
; les différentes possibilités sont
• DEFAULT_OPTION
• YES_NO_OPTION
• YES_NO_CANCEL_OPTION
• OK_CANCEL_OPTION
showOptionDialog : selon le tableau d’objets
passé en paramètre

ibbousetta@gmail.com BOUSETTA Ibrahim


Valeurs retournées par les méthodes

showConfirmDialog : une des constantes


OK_OPTION
CANCEL_OPTION
YES_OPTION
NO_OPTION
CLOSED_OPTION
showInputDialog : le texte (String) qu’a
choisi ou tapé l’utilisateur
showOptionDialog : le numéro du bouton sur
lequel l’utilisateur a cliqué ou CLOSED_OPTION

ibbousetta@gmail.com BOUSETTA Ibrahim


Message d’information

Le dialogue peut se limiter à un simple


message envoyé à l’utilisateur qui indique
qu’il a reçu le message en cliquant un
bouton

JOptionPane.showMessageDialog( frame, "ceci est un


message d'information.");

ibbousetta@gmail.com BOUSETTA Ibrahim


Message d’erreur

JOptionPane.showMessageDialog( frame, "Le message


d’erreur", "Titre fenêtre dialogue",
JOptionPane.ERROR_MESSAGE);

ibbousetta@gmail.com BOUSETTA Ibrahim


Saisie d’une valeur

Le dialogue permet à l’utilisateur de saisir une


valeur renvoyée
String nombre = JOptionPane.showInputDialog(
"Donnez un nombre");
Il peut même être utilisé dans un
environnement non graphique

ibbousetta@gmail.com BOUSETTA Ibrahim


Confirmation pour quitter
Demander une confirmation pour quitter une application :
setDefaultCloseOperation(
WindowConstants.DO_NOTHING_ON_CLOSE);
...
int reponse = JOptionPane.showConfirmDialog( this,
"Voulez-vous vraiment quitter ?", "Quitter l'application",
JOptionPane.YES_NO_OPTION);
if (reponse == JOptionPane.YES_OPTION) {
System.exit(0);
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Fenêtres de dialogue complexes

Pour les fenêtres de dialogue plus complexes ou


non modales, il faut hériter de la classe Jdialog
Voici, par exemple, le code d’une classe qui
affiche une fenêtre de dialogue qui demande un
nom d’utilisateur et un mot de passe (les
caractères tapés ne sont pas visibles)
Cet exemple montre comment initialiser la
fenêtre de dialogue, afficher la fenêtre, et
finalement récupérer les valeurs saisies par
l’utilisateur

ibbousetta@gmail.com BOUSETTA Ibrahim


Fenêtre de dialogue complexe
public class SaisieMDP extends Jdialog implements ActionListener
{
private JPasswordField zoneMDP;
private JButton valider, annuler;
private boolean ok;
public SaisieMDP(JFrame parent) {
super(parent, "Connexion", true);
Container contentPane = getContentPane();
// Panel pour mot de passe
JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(2, 2));
p1.add(new JLabel("Mot de passe :"));
p1.add(zoneMDP = new JPasswordField(""));
contentPane.add(p1, BorderLayout.CENTER);

ibbousetta@gmail.com BOUSETTA Ibrahim


Fenêtre de dialogue complexe

// Panel pour les boutons


JPanel p2 = new JPanel();
valider = new JButton(Valider);
valider.addActionListener(this);
p2.add(valider);
annuler = new JButton(Annuler);
valider.addActionListener(this);
p2.add(valider);
contentPane.add(p2, BorderLayout.SOUTH);
}
public char[] getMDP() {
return zoneMDP.getPassword();
}

ibbousetta@gmail.com BOUSETTA Ibrahim


public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == valider)
ok = true;
else if (evt.getSource() == annuler)
ok = false;
setVisible(false);
}
public boolean afficheDialog() {
ok = false;
setVisible(true); // reste coincé ici jusqu’au clic
// sur un des boutons valider ou annuler
return ok;
}
}

ibbousetta@gmail.com BOUSETTA Ibrahim


Utilisation de la fenêtre de dialogue
// this est une instance d’une sous-classe de JFrame
SaisieMDP smdp = null;
char[] mdp; // le mot de passe
...
if (smdp == null)
smdp = new SaisieMDP(this);
// afficheDialog() affiche la fenêtre de dialogue.
// Le programme ne passe à la ligne suivante que
// lorsque cette fenêtre est effacé par le clic du
// bouton de validation ou d’annulation de la fenêtre
if (smdp.afficheDialog()) {
// récupère le mot de passe
mdp = smdp.getMDP();
}
ibbousetta@gmail.com BOUSETTA Ibrahim
Fenêtres de dialogue particulières
JFileChooser pour choisir un fichier
3 types :
pour ouvrir
pour sauvegarder
à personnaliser
JColorChooser pour choisir une couleur

ibbousetta@gmail.com BOUSETTA Ibrahim


Exemple pour JFileChooser

JFileChooser fc = new JFileChooser(".");


// Affiche la fenêtre de dialogue dans la frame
// pour choisir un fichier...
int returnVal = fc.showOpenDialog(frame);
if(returnVal == JFileChooser.APPROVE_OPTION) {
File fichier = fc.getSelectedFile();
if (fichier != null) ouvreFichier(fichier);
}
// ... ou pour choisir le fichier de "sauvegarde"
int returnVal = fc.showSaveDialog(frame);
// idem ci-dessus. . .
sauveFichier(fichier);

ibbousetta@gmail.com BOUSETTA Ibrahim


Pouvoir choisir un répertoire

Par défaut on ne peut choisir de répertoire : un


double clic sur un répertoire ouvre le répertoire
mais ne le choisit pas
Pour un autre comportement il faut utiliser la
méthode setFileSelectionMode en lui passant
la constante DIRECTORIES_ONLY ou
FILES_AND_DIRECTORIES de la classe
JFileChooser
Par défaut le mode est FILES_ONLY
On peut indiquer si on autorise la sélection de
plusieurs fichiers :
setMultiSelectionEnabled(boolean b)
ibbousetta@gmail.com BOUSETTA Ibrahim
JTable

Utilité
Représenter des données sous forme
tabulaire :
Les lignes et les colonnes sont identifiées par
un nombre entier (en commençant à 0)

ibbousetta@gmail.com BOUSETTA Ibrahim


Tables simples

Les tables les plus simples sont construites avec


les constructeurs qui prennent en paramètres 2
tableaux d’Object ou 2 Vector (1 pour les noms
des colonnes et 1 pour les données)
On n’a pas à créer une classe pour le modèle de
données
La table utilise les tableaux ou vecteurs passés
en paramètres comme modèles (ils sont donc
modifiés si les données de la table le sont)

ibbousetta@gmail.com BOUSETTA Ibrahim


Exemple de table simple

Object[][] data = {{"a11", "a12"}, {"a21",


"a22"}};
String[] nomsColonnes = {"Col1", "Col2"};
JTable table = new JTable(data, nomsColonnes);
JScrollPane sp = new JScrollPane(table);
// Si on veut définir la taille de la zone
// d’affichage :
table.setPreferredScrollableViewportSize(
new Dimension(500, 70));

ibbousetta@gmail.com BOUSETTA Ibrahim


Table en dehors d’un ScrollPane

Le plus souvent les tables sont dans un


JScrollPane
Sinon, il faut faire afficher explicitement les en-
têtes de colonnes ; par exemple :
container.setLayout(new BorderLayout());
container.add(table.getTableHeader(),
BorderLayout.NORTH);
container.add(table, BorderLayout.CENTER);

ibbousetta@gmail.com BOUSETTA Ibrahim


Constructeurs de JTable

JTable() : crée une table avec un modèle de données


de type DefaultTableModel (utilise un Vector de Vector
pour ranger les données) et un modèle de colonnes de
type DefaultTableColumnModel
JTable(int ligne, int colonne) : des lignes et des
colonnes dont les cellules ne contiennent rien (null)

ibbousetta@gmail.com BOUSETTA Ibrahim


Méthodes de TableModel

Accéder aux données du modèle ou les modifier :


{get|set}valueAt
Indiquer si une cellule est modifiable :
isCellEditable
Décrire les colonnes : getColumnCount,
getColumnName, getColumnClass
Nombre de lignes : getRowCount
Ajouter ou enlever des écouteurs :
{add|remove}TableModelListener

ibbousetta@gmail.com BOUSETTA Ibrahim


Modèles de données
AbstractTableModel implémente l’interface TableModel
Elle est abstraite car elle n’implémentant que les méthodes
associées aux écouteurs
On l’utilise le plus souvent si on veut un modèle de données
explicite
Pour avoir un modèle en héritant de AbstractTableModel
il suffit de définir les 3 méthodes suivantes :
int getRowCount()
int getColumnCount()
Object getValueAt(int ligne, int colonne)
Le plus souvent il faut aussi redéfinir les méthodes qui
décrivent les colonnes :
String getColumnName() ; par défaut, elles s’appellent A, B,..
Class getColumnClass() ; par défaut, cette méthode renvoie
Object et aucun format particulier n’est utilisé pour l’affichage
ibbousetta@gmail.com BOUSETTA Ibrahim
setValueAt
La méthode setValueAt qui permet de modifier les valeurs du
modèle est implémentée dans AbstractTableModel, mais elle
est vide
Quand les données de la table sont modifiables, il faut donc
redéfinir cette méthode
Sinon, même les modifications de l’utilisateur avec un éditeur
de cellules, ne sont pas prises en compte par la table (les
éditeurs appellent setValueAt pour modifier la table)
Dans cette méthode, on doit le plus souvent avertir les
observateurs du modèle de la table qu’une donnée a été
modifiée
En effet, il faut au moins avertir la Jtable elle-même qui écoute
son modèle, sinon elle n’affichera pas les modifications par la
suite
Pour cela, la méthode doit appeler la méthode void
fireTableCellUpdated(int ligne, int colonne) définie dans la
classe AbstractTableModel
ibbousetta@gmail.com BOUSETTA Ibrahim
Ajouter un écouteur

JTable table= new JTable();


table.getModel().addTableModelListener(
new EcouteurModeleTable());
La table construite avec un modèle de données
écoute automatiquement son modèle
On peut aussi ajouter d’autres écouteurs avec la
méthode addTableModelListener

ibbousetta@gmail.com BOUSETTA Ibrahim


Écouteurs des modifications d’une table

Ils implémentent TableModelListener qui a une


seule méthode
tableChanged(TableModelEvent e)
On peut interroger e par
getFirstRow,
getLastRow,
getColumn,
getType (type de l’événement : INSERT et DELETE
pour insertion et suppression de lignes ou colonnes,
UPDATE pour une modification de données)

ibbousetta@gmail.com BOUSETTA Ibrahim


Exemple d’écouteur de table

class EcouteurModeleTable implements TableModelListener {


public void tableChanged(TableModelEvent e) {
int row = evt.getFirstRow();
int column = evt.getColumn();
Object data = ((TableModel)e.getSource()).
getValueAt(row,column);
traiter(data);
}
private void traiter(Object o) { . . . };
}

ibbousetta@gmail.com BOUSETTA Ibrahim


DefaultTableModel

DefaultTableModel hérite de AbstractTableModel ;


elle utilise un Vector de Vector pour ranger les
données
Si les données viennent d’une base de données,
DefaultTableModel ne convient pas et il faut hériter de
AbstractTableModel
JTable offre maintenant beaucoup de possibilités de
configuration, donc le plus souvent on héritera directement
AbstractTableModel plutôt que de DefaultTableModel

ibbousetta@gmail.com BOUSETTA Ibrahim


Renderers

Les « renderers » sont associés aux colonnes


Par défaut, ils dépendent des types des données
des colonnes
On peut aussi associer son propre renderer à une
colonne

ibbousetta@gmail.com BOUSETTA Ibrahim


Exemple de renderer
• Un combobox comme renderer

ibbousetta@gmail.com BOUSETTA Ibrahim


Éditeur de cellule
Par défaut, on a un éditeur par type de données
On peut associer son propre éditeur à une classe des
données de la table
On peut aussi en associer un à une colonne de la
table par la méthode setCellEditor de la classe
javax.swing.table.TableColumn ; par
exemple,table.getColumnModel().getColumn(2).
setCellEditor(editeur);

ibbousetta@gmail.com BOUSETTA Ibrahim


DefaultCellEditor
La classe DefaultCellEditor a des constructeurs
pour avoir des éditeurs qui sont des JTextField,
JComboBox ou JCheckBox
Par exemple, editeur = new
DefaultCellEditor(comboBox);
On peut aussi construire d’autres types d’éditeur en
implémentant directement l’interface TableCellEditor

ibbousetta@gmail.com BOUSETTA Ibrahim


DefaultCellEditor
• La classe DefaultCellEditor fait un
appel à la méthode setValueAt du
modèle de données de la table

ibbousetta@gmail.com BOUSETTA Ibrahim


Exemple d’éditeur
Un éditeur pour une colonne qui contient des
couleurs favorites

ibbousetta@gmail.com BOUSETTA Ibrahim


Sélection par l’utilisateur

Par défaut l’utilisateur peut sélectionner


une ou plusieurs lignes (pas
nécessairement contiguës) en cliquant
dessus
On peut changer ce mode de sélection par
la méthode setSelectionMode
On peut enregistrer des écouteurs de
sélection qui réagiront à une nouvelle
sélection

ibbousetta@gmail.com BOUSETTA Ibrahim


Sélection de lignes ou de colonnes

// On ne permet la sélection que d’1 ligne


table.setSelectionMode(ListSelectionModel.SINGLE_SEL
ECTION);
...
// Récupère le modèle pour la sélection
ListSelectionModel rowSM = table.getSelectionModel();
// Pour y ajouter un écouteur
rowSM.addListSelectionListener( new
EcouteurSelection());

ibbousetta@gmail.com BOUSETTA Ibrahim


Écouteur de sélection d’une ligne
class EcouteurSelection implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) return;
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty()) {
... // aucune sélection
}
else {
int nLigne = lsm.getMinSelectionIndex();
... // Traitement pour la sélection
}
}
}
ibbousetta@gmail.com BOUSETTA Ibrahim
Variante : sélection de plusieurs
lignes (pas toutes contiguës)

...
else {
int minIndex = lsm.getMinSelectionIndex();
int maxIndex = lsm.getMaxSelectionIndex();
for (int i = minIndex; i <= maxIndex; i++) {
if (lsm.isSelectedIndex(i)) {
// Ligne i est sélectionnée
...
}
}
}
ibbousetta@gmail.com BOUSETTA Ibrahim
Problème de fermeture

Le clic sur l'icône de fermeture ne quitte pas


l'application mais se contente de cacher la
fenêtre. Le processus continue de réquisitionner
de la mémoire, ce qui peut devenir très gênant
dans le cas de grosses applications.
La solution consiste à écouter l'événement de clic
sur cet icône et d'exécuter une instruction
fermant proprement l'application.
Java va alors, vider la mémoire occupée par tous
les objets de votre programme.

ibbousetta@gmail.com BOUSETTA Ibrahim


public TestJFrame(){
…..

addWindowListener(new WindowAdapter(){

public void windowClosing(WindowEvent we){


System.out.println("fermeture");
System.exit(0);
}

});
….

ibbousetta@gmail.com BOUSETTA Ibrahim


Evenement relatif aux fenetres
windowActivated(WindowEvent e)
Appelée lorsque la fenêtre est sur le point de devenir la fenêtre
active
windowClosed(WindowEvent e)
Appelée lorsqu'une fenêtre a été fermée suite à l'appel a dispose().
windowClosing(WindowEvent e)
Appelée quand l'utilisateur tente de fermer la fenêtre depuis le
menu système ou par un clic sur l'icône de fermeture.
windowOpened(WindowEvent e)
Appelée la première fois que la fenêtre est rendue visible
windowDeactivated(WindowEvent e)
Appelée lorsqu'une fenêtre n'est plus la fenêtre active
windowDeiconified(WindowEvent e)
Appelée lorsque la fenêtre passe de l'état d'icône à l'état normal.
windowIconified(WindowEvent e)
Appelée lorsque la fenêtre passe de l'état normal à l'état d'icône.
ibbousetta@gmail.com BOUSETTA Ibrahim
BOUSETTA Ibrahim

Vous aimerez peut-être aussi