Vous êtes sur la page 1sur 55

Interface graphique en Java

L2

Guillaume Wisniewski
guillaume.wisniewski@limsi.fr

LIMSI — CNRS

9 février 2009

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 1/1


Première partie I

Introduction

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 2/1


Remarque liminaire

un des grands avantages de Java : présence de bibliothèques


facilitant le développement d’interface graphique multiplateforme dès
les premières versions
aujourd’hui : de moins en moins d’applications « natives »
tout se fait dans le navigateur (gmail, ...)
interface graphique = ajax, flash, ...
mais les principes sont les mêmes
java omniprésent pour les traitements sur les serveurs

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 3/1


Base de la programmation d’interface

Un nouveau type de programmes


avant : déroulement du programme prévisible
maintenant : réagir aux actions de l’utilisateur

Bibliothèque Java standard


AWT (Abstract Windowing Toolkit) : premier paquetage graphique,
ancien, mieux supporté ( ?).
SWING Basé sur AWT, plus récent, mieux optimisé, plus riche (plus
de widgets), plus beau !

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 4/1


SWING : les concepts

Réaliser une interface graphique fait intervenir plusieurs composants


(toujours des classes) Swing :
top-level : c’est la racine de l’application graphique ( JFrame ,
JDialog ou JApplet ) ;
conteneurs intermédiaires : ils contiennent d’autres composants et
structurent l’application graphique ( JPanel , JScrollPane ,
JSplitPane , JToolBar , ...) ;
composants atomiques : JButton , JList , JLabel , JMenu , ...
layout-managers : ils servent à décrire le placement des composants
événements : ils permettent d’associer un traitement à une action

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 5/1


Une première application

import javax.swing.*;

public class PremFen {

public static void main (String args[]) {


JFrame fen = new JFrame();
fen.setSize(300,150);
fen.setTitle("Ma première fenêtre !");
fen.setVisible(true);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 6/1


Résultat

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 7/1


Deuxième méthode
import javax.swing.*;

class MaFenetre extends JFrame {

public MaFenetre() {
this.setSize(300,150);
this.setTitle("Ma seconde fenetre !");
}

public class PremFen2 {

public static void main (String args[]) {


JFrame fen = new MaFenetre() ;
fen.setVisible(true) ;
}
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 8/1
Deuxième partie II

Événements

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 9/1


Les événements

caractéristique principale d’une interface graphique


objets généralement créés par des composants atomiques qu’on
aura introduit dans la fenêtre (boutons, menus, boı̂tes de dialogue, ...)
Les événements font entrer en relation deux types d’objets :
les sources : ce sont les objets ayant donné naissance à l’événement
(bouton, fenêtre, ...)
les écouteurs : ce sont des objets associés aux sources dont la
classe implémente une interface correspondant à une catégorie
d’événements

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 10 / 1


Les événements : utilisation

1 les écouteurs s’enregistrent auprès d’un composant par la méthode


de addXxxListener (méthode du composant)
2 l’utilisateur agit sur un composant ; celui-ci devient une source
3 la source notifie l’événement de type XxxEvent à l’ensemble des
écouteurs qui se sont enregistrés

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 11 / 1


Un premier événement : clic dans une fenêtre (1/3)

Nous souhaitons écrire un message à chaque fois qu’un clic survient dans
notre fenêtre :
la source est la fenêtre elle-même ;
la classe d’événements liée à la souris est MouseEvent
l’interface MouseListener que l’écouteur doit implémenter comporte
cinq méthodes correspondant chacune à un événement particulier :
mousePressed (bouton pressé sur un composant)
mouseReleased (bouton relaché sur un composant)
mouseEntered (la souris entre dans un composant)
mouseExited (la souris sort d’un composant)
mouseClicked (bouton cliqué sur un composant)
ces méthodes sont appelées par la source dès que l’utilisateur réalise
l’action correspondante

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 12 / 1


En pratique I

import javax.swing.*;
import java.awt.event.*;
class MaFenetre extends JFrame implements MouseListener {

public MaFenetre() {
this.setSize(300,150);
this.setTitle("Gestion des clics");
// enregistre l’écouteur
// ici une même classe est source et écouteur
this.addMouseListener(this);
}

public void mouseClicked (MouseEvent ev) {


// gestion du clic
System.out.println("Clic dans la fenetre !");

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 13 / 1


En pratique II

// méthode vide (interface)


public void mousePressed (MouseEvent ev) {}
public void mouseReleased(MouseEvent ev) {}
public void mouseEntered (MouseEvent ev) {}
public void mouseExited (MouseEvent ev) {}
}

public class Clic {


public static void main (String args[]) {
JFrame fen = new MaFenetre();
fen.setVisible(true);
}
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 14 / 1


Résultat

Remarques :
autre méthode : créer un objet ObjetEcouteur et en passer la
référence à la méthode AddMouseListener
les événements ont des attributs :
System.out.println("clic " + ev.getX() + " " + ev.getY());

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 15 / 1


Écouteurs/adaptateurs
Avoir à implémenter toutes les méthodes de l’interface dans l’écouteur
n’est pas toujours très pratique.
Pour faciliter les choses, JAVA dispose toujours d’une classe qui
implémente toutes les méthodes d’une interface donnée avec un corps
vide : l’adaptateur
pour XxxEvent , l’adaptateur est XxxAdapter
si on veut comme dans l’exemple que la classe soit aussi l’écouteur il
faudra utiliser une classe anonyme
class MaFenetre extends JFrame {
// ...
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent ev) {
//...
}
}) ;
// ...
}
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 16 / 1
Troisième partie III

Organisation d’une fenêtre

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 17 / 1


Où placer les composants ? (1/2)

fenêtre = ensemble de composants (boutons, zone de texte, barre de


menu, ...)
comment organiser tous ces composants ?
les composants top-level (comme JFrame) possedent une barre de
menu et un contenu (le content-pane de type Container) qui contient
tous les composants visibles

La méthode getContentPane donne la référence au contenu où on


pourra ajouter un composant avec la méthode add .
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 18 / 1
Où placer les composants ? (2/2)

La disposition des composants dans une fenêtre est gérée par un


gestionnaire de mise en forme (le layout-manager)
il en existe plusieurs utilisant des règles spécifiques pour disposer les
composants ;
par défaut Java utilise BorderLayout avec lequel en l’absence
d’informations un composant occupe toute la fenêtre
pour choisir un gestionnaire, il faut appliquer la méthode setLayout
à l’objet contenu de la fenêtre : pour utiliser par exemple FlowLayout
(affichant les composants comme les mots d’un texte) on peut
invoquer getContentPane().setLayout(new FlowLayout());

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 19 / 1


Conteneur graphique

pour créer des interfaces « complexes » : hiérarchie de conteneur


chaque conteneur représente un ensemble de composants
chaque conteneur a son propre layout manager

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 20 / 1


Code correspondant

JFrame frame = new JFrame("Example JFrame");

Container container1 = frame.getContentPane();


JPanel container2 = new JPanel();
container2.setBackground(new Color(0, 0, 200));
JTextField component1 = new JTextField("component1");
JCheckBox component2 = new JCheckBox("component2");
container1.add(container2);
container2.add(component1);
container2.add(component2);
JButton component3 = new JButton("component3");
container1.add(component3);

frame.pack();
frame.setVisible(true);

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 21 / 1


Quatrième partie IV

Composants

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 22 / 1


Premier composant : le bouton

Pour utiliser un composant bouton il s’agı̂t tout d’abord de le créer et de le


placer :
on crée un objet bouton en utilisant le constructeur de la classe
JButton à qui on donne le label du bouton :
JButton monBouton = new JButton("Un bouton");
on place ce bouton dans le contenu de la fenêtre en récupérant une
référence vers ce contenu et en ajoutant le bouton avec la méthode
add :
Container contenu = getContentPane();
contenu.add(monBouton);
on indique comment disposer ce bouton avec le gestionnaire de mise
en forme de notre choix :
getContentPane().setLayout(new FlowLayout());

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 23 / 1


Code complet I

import javax.swing.*;
import java.awt.*;

class FenBouton1 extends JFrame {

private JButton monBouton;

public FenBouton1() {
this.setSize(300,150) ;
this.setTitle("Premier bouton");
this.monBouton = new JButton("Un bouton");
this.getContentPane().setLayout(new FlowLayout());
this.getContentPane().add(monBouton);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 24 / 1


Code complet II

public class Bouton1 {

public static void main (String args[]) {


JFrame fen = new FenBouton1();
fen.setVisible(true);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 25 / 1


Résultat

ce bouton ne fait rien


utiliser l’événement Action :
créer un écouteur qui sera un objet d’une classe implémentant
l’interface ActionListener
associer cet écouteur au bouton par la méthode addActionListener

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 26 / 1


Bouton avec événements I

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class FenBouton2 extends JFrame implements ActionListener {

private JButton monBouton;

public FenBouton2() {
this.setSize(300, 150);
this.setTitle("Second bouton");
this.monBouton = new JButton("Un bouton");
this.getContentPane().setLayout(new FlowLayout());
this.getContentPane().add(monBouton);
this.monBouton.addActionListener(this);

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 27 / 1


Bouton avec événements II
}

public void actionPerformed (ActionEvent ev) {


System.out.println("action sur monBouton");
}

public class Bouton2 {

public static void main (String args[]) {


JFrame fen = new FenBouton2();
fen.setVisible(true);
}

}
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 28 / 1
Résultat

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 29 / 1


Gérer plusieurs composants

Le problème
fenêtre = ensemble de composants ; en général plusieurs
composants du même type (p.ex. une fenêtre avec deux boutons)
comment attacher un comportement différent à chacun des
composants

Les deux solutions


1 routage « à priori » : classe écouteur différente pour chaque
composant
2 routage « à posteriori » : méthode getSource qui fournit une
référence sur l’objet ayant déclenché l’événement ⇒ permet
d’identifier l’émetteur

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 30 / 1


En pratique I

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class FenBouton3 extends JFrame implements ActionListener {


private JButton bouton1;
private JButton bouton2;

public FenBouton3() {
this.setSize(300,150);
this.setTitle("Deux boutons");
this.bouton1 = new JButton("Bouton 1");
this.bouton2 = new JButton("Bouton 2");

this.getContentPane().setLayout(new FlowLayout());

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 31 / 1


En pratique II
this.getContentPane().add(bouton1);
this.getContentPane().add(bouton2);
this.bouton1.addActionListener(this);
this.bouton2.addActionListener(this);
}

public void actionPerformed (ActionEvent ev) {


if (ev.getSource() == this.bouton1) {
// Ou encore
// if (ev.getActionCommand() == "Bouton 1")
System.out.println("action sur bouton1");
} else {
System.out.println("action sur bouton2") ;
}
}
}
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 32 / 1
En pratique III

public class Bouton3 {

public static void main (String args[]) {


JFrame fen = new FenBouton3();
fen.setVisible(true);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 33 / 1


Résultat

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 34 / 1


Les composants (1)

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 35 / 1


Les composants (2)

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 36 / 1


Les composants (3)

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 37 / 1


Cinquième partie V

Dessin

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 38 / 1


Base du dessin en Java

possibilité de dessiner n’importe quel composant en utilisant des


fonctions de dessin
pour éviter que le dessin ne disparaisse après un réaffichage de la
fenêtre (par exemple après un déplacement) il faut le placer dans une
méthode particulière du composant appelée paintComponent
pas indispensable, mais c’est le plus pratique

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 39 / 1


Création d’un panneau

Un panneau est un conteneur : il doit être attaché à un autre conteneur


(par exemple le contenu de la fenêtre) et peut contenir soit d’autres
conteneurs, soit des composants atomiques (boutons, textes...)
par défaut un panneau n’a pas de bordure et sa couleur est celle du
conteneur (il est invisible)
on peut utiliser sa methode setBackground recevant un objet de type
Color
comme les composants, il s’attache au contenu par la méthode add

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 40 / 1


Exemple I

import javax.swing.*;
import java.awt.*;

class FenPanneau1 extends JFrame {


private JPanel monPanneau;

public FenPanneau1() {
this.setSize(300,150);
this.setTitle("Premier panneau");
this.monPanneau = new JPanel();
this.monPanneau.setBackground(Color.yellow);
this.getContentPane().add(monPanneau);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 41 / 1


Exemple II

public class Panneau1 {

public static void main (String args[]) {


JFrame fen = new FenPanneau1();
fen.setVisible(true);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 42 / 1


Dessin dans un panneau

Pour créer un dessin permanent dans un composant, il faut redéfinir sa


méthode paintComponent
redéfinition d’une méthode de JPanel ⇒ hériter de Jpanel
méthode à redéfinir :
public void paintComponent (Graphics g)
argument = contexte graphique
CG dispose des méthodes de dessin et des paramètres courants
(police, couleur de fond, etc.)
La méthode paintComponent de Jpanel dessinait le composant, il
est nécessaire de l’appeler avant de réaliser ses propres dessins par
super.paintComponent(g);

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 43 / 1


En pratique I

import javax.swing.*;
import java.awt.*;

class Panneau extends JPanel {

public void paintComponent(Graphics g) {


super.paintComponent(g);
g.drawLine(15,10,100,50);
}

class FenPanneau2 extends JFrame {


private Panneau monPanneau;

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 44 / 1


En pratique II
public FenPanneau2() {
this.setSize(300,150) ;
this.setTitle("Second panneau");
this.monPanneau = new Panneau();
this.monPanneau.setBackground(Color.yellow);
getContentPane().add(monPanneau);
}

public class Panneau2 {

public static void main (String args[]) {


JFrame fen = new FenPanneau2();
fen.setVisible(true);
}
G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 45 / 1
En pratique III

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 46 / 1


Forcer le dessin

Pour changer un dessin en cours d’exécution il faudra forcer l’appel à


paintComponent
c’est l’appel à la méthode repaint qui force l’appel à paintComponent
la méthode paintComponent devra réagir en fonction du contexte
Pour dessiner à la volée (au fur et à mesure des actions de l’utilisateur) :
la permanence des dessins n’est plus assurée
il faut récupérer le contexte graphique du composant à redessinner
grâce à la méthode getGraphics
il faudra libérer les ressources occupées par le contexte graphique
par la méthode dispose

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 47 / 1


Forcer le dessin : exemple I

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class Panneau extends JPanel {


private boolean rectangle;
private boolean ovale;

public Panneau() {
this.rectangle = false;
this.ovale = false;
}

public void setRectangle() {


this.rectangle = true;

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 48 / 1


Forcer le dessin : exemple II
this.ovale = false;
}

public void setOvale() {


this.rectangle = false;
this.ovale = true;
}

public void paintComponent(Graphics g) {


// Appel de la fonction de la mère
super.paintComponent(g);
// Dessin en fonction du contexte
if (this.ovale) {
g.drawOval(80,20,120,60);
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 49 / 1


Forcer le dessin : exemple III
if (this.rectangle) {
g.drawRect(80,20,120,60);
}
}

class FenPanneau3 extends JFrame implements ActionListener {


private Panneau monPanneau;
private JButton rectangle;
private JButton ovale ;

public FenPanneau3() {
this.setSize(300,170);
this.setTitle("Troisieme panneau");

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 50 / 1


Forcer le dessin : exemple IV
Container contenu = getContentPane();

this.monPanneau = new Panneau();


contenu.add(monPanneau);

this.rectangle = new JButton("Rectangle");


this.rectangle.addActionListener(this);
contenu.add(rectangle,"North");

this.ovale = new JButton("Ovale");


this.ovale.addActionListener(this);
contenu.add(ovale,"South");
}

public void actionPerformed(ActionEvent ev) {


G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 51 / 1
Forcer le dessin : exemple V

if (ev.getSource() == rectangle) {
this.monPanneau.setRectangle();
}

if (ev.getSource() == ovale) {
this.monPanneau.setOvale();
}

this.monPanneau.repaint();

public class Panneau3 {


G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 52 / 1
Forcer le dessin : exemple VI

public static void main (String args[]) {


JFrame fen = new FenPanneau3();
fen.setVisible(true) ;
}

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 53 / 1


Résultat

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 54 / 1


Quelques méthodes de dessin

drawLine(x1, y1, x2, y2) trace une ligne, les paramètres étant
les coordonnées des deux sommets ;
drawRect(x, y, largeur, hauteur) trace un rectangle, les deux
premier paramètres sont les coordonnées du coin supérieur gauche ;
drawOval(x, y, largeur, hauteur) même chose que pour le
rectangle mais dessine un ovale ;
drawRoundRect(x, y, largeur, hauteur, diamh, diamv)
trace un rectangle aux bords arrondis, les deux derniers paramètres
sont le diamètre horizontal et vertical de l’arc aux quatre coins
et aussi drawArc, drawPolygon, drawPolyLine etc.

G. Wisniewski (LIMSI — CNRS) Interface graphique en Java L2 9 février 2009 55 / 1