Programmation événementielle
& interfaces graphiques Java Swing
Eric Lecolinet
Télécom Paristech – Dept. INFRES
www.telecom-paristech.fr/~elc
Page 1 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Toolkits graphiques Java
Pour le Desktop
– Swing
– JavaFX
nouveau, inspiré du Web
– AWT Components
obsolète
– SWT
Eclipse Foundation
Swing
– est multi-plateformes
– repose sur AWT Components mais pas la même chose !
– attention : JButton != Button !
Page 2 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Composants Swing
Source: documentation IBM
Page 3 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Interacteurs
Page 4 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Boutons
JButton JCheckbox : JRadioButton :
choix idépendants choix exclusif : cf. ButtonGroup
Source: documentation Java Oracle
Page 5 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Texte
JTextField
JPasswordField
JTextArea :
texte simple multilignes
Ascenseurs :
JScrollPane JEditorPane : texte avec styles
compatible HTML et RTF
Page 6 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Conteneurs
JPanel: conteneur générique
... JScrollPane:
avec ascenseurs intégrés
JSplitPane:
avec « diviseur » intégré
Page 7 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Conteneurs
JToolBar: barre d’outils
(sous la barre de menus)
JTabbedPane:
onglets
JTree
JTable
Page 8 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Conteneurs spécifiques
JInternalFrame JLayeredPane permet de superposer
des composants
à placer dans un JDesktopPane
qui joue le rôle de bureau virtuel voir aussi JRootPane présenté plus loin
JDesktopPane hérite de JLayeredPane
Page 9 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Fenêtres
JFrame : fenêtre principale de l’application
JDialog : fenêtre secondaire
– normalement dépendante de la JFrame :
• pas d’iconification séparée, toujours au dessus de la JFrame
– souvent temporaire et modale :
• bloque l’interaction, impose à l’utilisateur de répondre
Page 10 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Fenêtres
JRootPane implicitement créé
– par JApplet, JDialog, JFrame
– et JInternalFrame
Page 11 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Boîtes de dialogue prédéfinies
JFileChooser JColorChooser
Particularité
– peuvent être créés :
• comme composants internes
• ou comme boîtes de dialogue
JOptionPane (multiples variantes)
Page 12 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Applets
Applet = composant de premier niveau
– pour les applications dans pages Web
Attention
– restrictions (accès aux fichiers,
sockets...) pour des raisons de sécurité
Page 13 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Menus
raccourci
clavier
(accelerator)
mnémonique
Page 14 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Arbre d’instanciation
Arbre d’instanciation
– arbre de filiation des instances de composants graphiques
Page 15 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Arbre d’instanciation
Chaque objet graphique « contient » ses enfants
– superposition : enfants affichés au dessus des parents
– clipping : enfants « découpés » : ne dépassent pas des parents
Page 16 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Arbre d’instanciation
Attention : ne pas confondre avec l’arbre d’héritage !
– arbre d’instanciation = arbre de filiation des instances
– arbre d’héritage = hiérarchie des classes
Page 17 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Arbre d’instanciation
Objet de plus haut niveau de l’arbre
– JFrame (JApplet pour applets Java)
Les conteneurs peuvent être emboîtés
– en particulier les JPanels
Les layout managers assurent la disposition spatiale
– un layout manager par conteneur
– défaut pour JPanel : FlowLayout, pour JWindow : BorderLayout, etc.
Ne pas oublier d’appeler
– frame.pack( ) // calcul récursif des positions et des tailles
– frame.setVisible(true) // fait apparaître la fenêtre
Page 18 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 0
// donne accès aux composants Swing
import javax.swing.*;
public class BipBip extends JFrame { // fenêtre principale
JButton button = null;
public static void main(String argv[ ]) {
BipBip toplevel = new BipBip(); // en gris : optionnel
}
public BipBip() {
button = new JButton ("Please Click Me !");
getContentPane().add(button); // en gris : nécessaire avant version 5
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Bib Bip");
pack(); // calcule la disposition spatiale
setVisible(true); // fait apparaître l’interface
}
}
Page 19 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 0
Notes et rappels
– package javax.swing
– une seule classe public par fichier, le fichier doit avoir le même nom
– button est une variable d’instance (on peut l’initialiser contrairement à C++)
– toplevel est une variable locale
– main() est une méthode de classe (cf. static)
– les méthodes d’instance ont automatiquement accès aux variables d’instance
elles ont un paramètre caché this qui pointe sur l’instance
– getContentPane() nécesaire avant la version 5 à cause du JRootPane
JWindow.add() a été redéfini dans les versions ultérieure de Java
Page 20 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Evénements
Evénements
– envoyés à l’application ciblée
– à chaque action élémentaire de l’utilisateur
Page 21 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Boucle de gestion des événements
Boucle infinie qui
– récupère les événements
– appelle les fonctions de callback des composants graphiques
Lancée automatiquement
– à la fin de la méthode main() dans le cas de Java
Page 22 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Pattern Observateur/Observé
Principe
– associer un(des) observateur(s) à un(des) objet(s) observé(s)
– observateur(s) notifié(s) automatiquement quand une certaine
condition se produit sur un observé
Page 23 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Application aux interfaces graphiques
Les observateurs détectent les événements
– ce sont des fonctions de callback (en C, C++...)
– ou des objets : Listeners en Java
• leurs méthodes font office de fonctions de callback
Page 24 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Evénements Java
Evénements AWT et Swing
– objets correspondant à des catégories d’évenements
– les principaux héritent de java.awt.event.AWTEvent
Evénements de “bas niveau”
– MouseEvent appuyer, relacher, bouger la souris ...
– KeyEvent appuyer, relacher une touche clavier...
– WindowEvent fermeture des fenêtres ....
– FocusEvent focus clavier (= où vont les caractères tapés au clavier)
– etc.
Evénements de “haut niveau”
– ActionEvent activer un bouton, un champ textuel ...
abstraction des événements de bas niveau
– TextEvent modification du texte entré
– etc.
Page 25 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Evénements Java
Méthodes communes aux AWTEvent
– getSource() objet producteur (Object)
– getID() type d’événement (int)
Exemple: méthodes de MouseEvent
– getX(), getY()
– getClickCount()
– getModifiers()
– getWhen()
– etc.
Page 26 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Observateurs d’événements
Event Listeners
– à chaque classe d’événement correspond une classe d’EventListener
(en général)
Exemple : ActionEvent
– Evénement : ActionEvent
– Listener : ActionListener
– Méthode : actionPerformed(ActionEvent)
Page 27 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Observateurs d’événements
Exemple : MouseEvent
– Evénement : MouseEvent
– Listener : MouseListener
– Méthodes :
– Listener : MouseMotionListener
• mouseClicked(MouseEvent)
– Méthodes :
• mouseEntered(MouseEvent)
• mouseDragged(MouseEvent)
• mouseExited(MouseEvent)
• mousePressed(MouseEvent) • mouseMoved(MouseEvent)
• mouseReleased(MouseEvent)
Remarque
– toutes les méthodes doivent être implémentées
– car les Listeners sont des interfaces (au sens du langage Java)
Page 28 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Rendre les composants réactifs
Associer des Listeners aux composants graphiques
– un composant peut avoir plusieurs listeners
– un même listener peut être associé à plusieurs composants
Page 29 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 1
import javax.swing.*;
import java.awt.event.*;
public class BipBip extends JFrame {
JButton button;
public static void main(String argv[ ]) { class Ecoute implements ActionListener
{
new BipBip();
} // méthode appelée quand on active le bouton
public void actionPerformed(ActionEvent e) {
public BipBip() { System.out.println("Done!");
button = new JButton ("Do It!"); }
add(button); }
// créer et associer un ActionListener
Ecoute elc = new Ecoute(); Problème ?
button.addActionListener(elc);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
Page 30 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 1
import javax.swing.*;
import java.awt.event.*;
public class BipBip extends JFrame {
JButton button;
JLabel label = new JLabel();
class Ecoute implements ActionListener
public static void main(String argv[ ]) { {
new BipBip(); public void actionPerformed(ActionEvent e) {
}
System.out.println("Done!");
public BipBip() { label.setText("Done!"); // ne compile pas !
button = new JButton ("Do It!"); }
add(button); }
// créer et associer un ActionListener
Ecoute elc = new Ecoute(); Problème :
button.addActionListener(elc); communication entre objets
setDefaultCloseOperation(EXIT_ON_CLOSE); – comment le Listener peut-il agir
pack();
setVisible(true);
sur les composants graphiques ?
}
} // fin de la classe BibBip
Page 31 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 1
import javax.swing.*; class Ecoute implements ActionListener {
import java.awt.event.*;
BipBip mainWin;
public class BipBip extends JFrame {
JButton button; public Ecoute (BipBip mainWin) {
JLabel label = new JLabel(); this.mainWin = mainWin;
}
public static void main(String argv[ ]) {
new BipBip();
public void actionPerformed(ActionEvent e) {
}
System.out.println("Done!");
public BipBip() { mainWin.label.setText("Done!");
button = new JButton ("Do It"); }
add(button); }
// créer et associer un ActionListener
Ecoute elc = new Ecoute(this);
button.addActionListener(elc); Solution
setDefaultCloseOperation(EXIT_ON_CLOSE); – le Listener a une référence
pack(); vers la partie graphique
setVisible(true);
} – solution flexible mais un peu lourde
} // fin de la classe BibBip
Page 32 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Objets hybrides
A la fois composant graphique et Listener
– un seul objet => plus de problème de communication entre objets !
– principe de l’héritage multiple
• simplifié dans le cas de Java : on peut « hériter » de plusieurs
spécifications (i.e. interfaces)
Page 33 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 2
import javax.swing.*;
import java.awt.event.*;
public class BipBip extends JFrame
implements ActionListener {
JButton button;
JLabel label = new JLabel();
public void actionPerformed(ActionEvent e) {
public static void main(String argv[ ]) {
label.setText("Done!");
new BipBip();
} }
public BipBip() { } // fin de la classe BibBip
add(button = new JButton ("Do It"));
// BibBip est à la fois un JFrame et un Listener Remarque
button.addActionListener(this);
– actionPerformed() à accès à label
setDefaultCloseOperation(EXIT_ON_CLOSE); car c’est une méthode d’instance
pack();
setVisible(true); de BibBip
}
Autre problème ?
Page 34 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 2
import javax.swing.*;
import java.awt.event.*;
public class BipBip extends JFrame
implements ActionListener {
JButton button;
JLabel label = new JLabel();
public void actionPerformed(ActionEvent e) {
public static void main(String argv[ ]) {
label.setText("Done!");
new BipBip();
}
}
public BipBip() { } // fin de la classe BibBip
add(button = new JButton ("Do It"));
// BibBip est à la fois un JFrame et un Listener
button.addActionListener(this); Problème : plusieurs boutons
– comment avoir plusieurs
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); comportements avec
setVisible(true); un seul Listener ?
}
Page 35 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 2
import javax.swing.*;
import java.awt.event.*; public void actionPerformed(ActionEvent e) {
public class BipBip extends JFrame if (e.getSource() == doIt)
implements ActionListener { label.setText("Done!");
JButton doIt, close; else if (e.getSource() == close)
JLabel label = new JLabel();
System.exit(0);
public static void main(String argv[ ]) { }
new BipBip(); }
}
public BipBip() { Solution
add(doIt = new JButton("Do It")); – distinguer les boutons grâce à :
add(close = new JButton("Close"));
• 1) getSource() ou
doIt.addActionListener(this); • 2) getActionCommand()
close.addActionListener(this);
– 1) plus sûre (ne dépend pas des noms)
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); – peu adapté si beaucoup de commandes
setVisible(true);
}
Page 36 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Avantages et inconvénients
Version 1 Version 2
– plus souple : – plus simple mais limitée :
autant de listeners que l'on veut on ne peut avoir qu'une seule
– mais peu concis : méthode actionPerformed()
on multiplie les objets et les lignes
– peu adapté si beaucoup de
de code commandes
Page 37 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
3eme solution : classes imbriquées
Classes définies à l’intérieur d’une autre classe
– ont accès aux variables d’instance des classes qui les contiennent
(c'est une forme de capture de variables)
– attention : ce n’est pas le cas en C++ !
Combinent les avantages des 2 solutions
précédentes
– souplesse sans la lourdeur !
Page 38 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple : version 3
import javax.swing.*; class DoItListener implements ActionListener {
import java.awt.event.*; public void actionPerformed(ActionEvent e) {
label.setText("Done!");
BipBip extends JFrame {
}
JButton doIt, close;
}
JLabel label = new JLabel();
public static void main(String argv[ ]) { class CloseListener implements ActionListener {
new BipBip(); public void actionPerformed(ActionEvent e) {
} System.exit(0);
}
public BipBip() { }
add( doIt = new JButton("Do It") ); } // fin de la classe BibBip
add( close = new JButton("Close") );
doIt.addActionListener(new DoItListener( ));
close.addActionListener(new CloseListener( ));
Note :
setDefaultCloseOperation(EXIT_ON_CLOSE); – actionPerformed() à accès à label
pack();
setVisible(true); car DoItListener est une classe
} imbriquée de BibBip
Page 39 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Synthèse
Page 40 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Remarques
Remarques
– les classes imbriquées peuvent également servir à encapsuler
l’implémentation
– le terme exact est classes internes (inner classes en Anglais)
– il existe aussi des classes imbriquées statiques = nested classes
• pour structurer en sous-parties
Page 41 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Classes imbriquées anonymes
Classes imbriquées... qui n’ont pas de nom !
public class BipBip extends JFrame {
JLabel label = new JLabel(); // label doit être une variable d’instance (pas une variable locale)
...... // car elle est référencée dans une méthode d’instance
public BipBip() {
JButton doIt = new JButton("Do It");
add(doIt);
doIt.addActionListener(new ActionListener( ) { // sous-classe anonyme de ActionListener
public void actionPerformed(ActionEvent e) {
label.setText("Done!");
}
});
......
}
Page 42 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Classes imbriquées anonymes
Classes imbriquées... qui n’ont pas de nom !
public class BipBip extends JFrame {
JLabel label = new JLabel(); Notes :
...... – ressemblent un peu aux lambdas
du C++11
public BipBip() { – les lambdas existent aussi
JButton doIt = new JButton("Do It"); en Java 8
add(doIt);
doIt.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e) {
label.setText("Done!");
}
});
......
}
Page 43 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Mélanger les plaisirs !
abstract class MyButton extends JButton implements ActionListener {
MyButton(String name) {
super(name);
addActionListener(this);
}
}
public class BipBip extends JFrame {
JLabel label = new JLabel();
......
public BipBip() {
add(new MyButton("Do It")) {
public void actionPerformed(ActionEvent e) {
label.setText("Done!");
}
});
......
Page 44 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Conflits
public class BipBip extends JFrame {
JButton close = new JButton("Close");
class CloseListener implements ActionListener {
boolean close = false
public void actionPerformed(ActionEvent e) {
setVisible(close); // OK
setVisible(BipBip.close); // FAUX : pas le bon « close »
this.setVisible(close); // ERREUR : pas le bon « this »
BipBip.this.setVisible(close); // OK
}
}
Même nom de variable dans classe imbriquante et classe imbriquée
⇒ 1) à éviter !
⇒ 2) préfixer par le nom de la classe
Page 45 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Remarques sur les constructeurs
abstract class MyButton extends JButton implements ActionListener {
public MyButton(String name, Icon icon) {
super(name, icon);
........
}
public MyButton (String name) {
this(name, null);
}
Un constructeur peut en appeler un autre
– C++ : possible en C++11
– C++ accepte les paramètres par défaut mais pas Java
Page 46 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Remarques sur les constructeurs
abstract class Toto {
static { // constructeur de classe
.......
}
Constructeur de classe
– sert à effectuer des opérations sur les variables de classe (initialisations)
– n’existe pas en C++ (mais on peut le simuler)
Page 47 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Dessin (classes imbriquées)
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Scribble extends JApplet {
private int last_x, last_y;
public void init( ) {
// ! NB: rajouter getContentpane(). avant Java 5 !
setBackground(Color.white);
// définir, instancier et enregistrer le Listener
addMouseListener(
new MouseAdapter ( ) {
public void mousePressed(MouseEvent e) {
last_x = e.getX( );
last_y = e.getY( );
}
} );
Page 48 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Dessin (classes imbriquées)
addMouseMotionListener(
new MouseMotionAdapter ( ) {
public void mouseDragged(MouseEvent e) {
Graphics g = getGraphics( );
int x = e.getX( );
int y = e.getY( );
g.drawLine(last_x, last_y, x, y);
last_x = x;
last_y = y;
}
} );
JButton b = new JButton("Clear"); // bouton qui efface tout
add(b);
b.addActionListener(
new ActionListener ( ) {
public void actionPerformed(ActionEvent e) {
Graphics g = getGraphics( );
g.setColor(getBackground( ));
g.fillRect(0, 0, getSize( ).width, getSize( ).height);
}
} );
Page 49 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Persistance de l’affichage
Problèmes de l’exemple précédent
– 1) l’affichage du dessin n’est pas persistant
• il est effacé si on déplace une fenêtre dessus, si on iconifie...
(en fait ça dépend des plateformes)
– 2) normalement les méthodes des listeners ne doivent pas dessiner
Solution
– mémoriser la liste des opérations graphiques dans une « display list »
– réafficher le dessin quand le composant qui le contient est rafraîchi
Page 50 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Réafficher le dessin (1)
Pour réafficher le dessin avec AWT
– redéfinir la méthode paint()
Pour réafficher le dessin avec Swing
– redéfinir la méthode paintComponent()
– paint() appelle paintComponent() puis paintBorder() puis paintChildren()
class Dessin extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g); // ne pas oublier cette ligne !
....etc...
}
}
Page 51 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Réafficher le dessin (2)
Pour indiquer qu’il faut réafficher le dessin
– repaint() dans les méthodes des Listeners
⇒ appel automatique de paint() quand on revient
dans la boucle de gestion des événements
Page 52 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Divers
Divers
– Appeler revalidate() dans certains cas de changements de taille
– Opacité des widgets
• certains composants sont opaques, d’autres sont transparents
• setOpaque() => composant opaque
– Taille des bords : getInsets()
Page 53 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
JFileChooser
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter
= new FileNameExtensionFilter ("JPG & GIF Images", "jpg", "gif"););
chooser.setFileFilter(filter);
Ouvre la boîte de dialogue et bloque l’interaction (dialogue modal) :
int returnVal = chooser.showOpenDialog(parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: "
+ chooser.getSelectedFile().getName());
}
Page 54 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Applets
Application
– Programme indépendant
• interprété par la commande java
– Structure
• hérite de JFrame (pour une GUI)
• méthode main()
• peut être interfacée avec un autre langage (interfaces natives)
Applet (appliquette)
– Programme pour navigateur Web
• interprété par navigateur Web ou commande appletviewer
• attention: restrictions d’accès (fichiers, sockets ...)
– Structure
• hérite de JApplet
• méthode init() (pas de new !)
Page 55 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Applet dans une page Web
Dans la page Web
<!-- Applet Scribble : code a inserer dans le fichier HTML -->
<html>
<body>
<applet code=”Scribble.class” width=”300” height=”300”> </applet>
</body>
</html>
Pour tester l’applet
– appletviewer fichier-html
– ou avec votre navigateur favori
Page 56 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Dessin dans une applet
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Scribble extends JApplet
implements MouseListener, MouseMotionListener
{
private int last_x, last_y;
public void init( ) {
// enregistrer les Listeners
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.setBackground(Color.white);
}
// méthode de l’interface MouseListener
public void mousePressed(MouseEvent e) {
last_x = e.getX( );
last_y = e.getY( );
}
Page 57 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Dessin dans une applet
// méthode de l’interface MouseMotionListener
public void mouseDragged(MouseEvent e) {
Graphics g = getGraphics( );
int x = e.getX( );
int y = e.getY( );
g.drawLine(last_x, last_y, x, y);
last_x = x;
last_y = y;
}
// méthodes inutilisées des Listeners
public void mouseReleased (MouseEvent e) { }
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseMoved(MouseEvent e) { }
}
Page 58 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Disposition spatiale
Les LayoutManagers
– calculent automatiquement la disposition spatiale des enfants
des Containers
A chaque conteneur est associé un LayoutManager
– qui dépend du type de conteneur
– qui peut être changé par la méthode setLayout() :
conteneur.setLayout(unAutreLayoutManager)
Pour faire le calcul "à la main"
– à éviter sauf cas particuliers :
conteneur.setLayout(null)
Page 59 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Avantages des LayoutManagers
C'est plus simple
– pas de calculs compliqués à programmer !
Configurabilité
– accessibilité : indépendance par rapport aux tailles des polices
– internationalisation : indépendance par rapport à la longueur du texte
• langues orientales : texte ~1/3 plus petit que l'anglais
• français, allemand : texte ~1/3 plus grand que l'anglais
Adaptativité des interfaces
– les composants graphiques se retaillent automatiquement
– quand l'utilisateur retaille les fenêtres
Page 60 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Principaux LayoutManagers
FlowLayout
– défaut des JPanel
– met les objets à la suite comme un "flux textuel" dans une page
• de gauche à droite puis à la ligne
Page 61 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Principaux LayoutManagers
BorderLayout
– défaut des JFrame et JDialog
– retaille automatiquement les enfants du conteneur
– disposition de type points cardinaux
• via constantes: BorderLayout.CENTER, EAST, NORTH, SOUTH, WEST
Page 62 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Principaux LayoutManagers (2)
GridLayout
– divise le conteneur en cellules de même taille (grille virtuelle)
• de gauche à droite et de haut en bas
– retaille automatiquement les enfants
Page 63 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Principaux LayoutManagers (2)
GridBagLayout
– grille + contraintes spatiales
• les enfants n'ont pas tous la même taille
• spécification par des
GridBagConstraints
Page 64 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Principaux LayoutManagers (3)
CardLayout
– empile les enfants (et les met à la même taille)
– usage typique: pour les onglets
BoxLayout
– disposition verticale ou horizontale
– exemple vu précédemment :
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
SpringLayout
– contraintes entre les bords des enfants
Page 65 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Autres toolkits graphiques Java
AWT Components
– plus ancien et moins puissant que Swing
– attention: même noms que Swing mais ... sans le J !
• exemple: JButton (Swing) et Button (AWT)
SWT
– "Standard Widget Toolkit"
– développé pour Eclipse
– open source
– même type d'architecture que AWT
Page 66 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
AWT versus Swing
■ AWT
– couche "abstraite" qui encapsule les widgets natifs de la plateforme
– look & feel différent suivant l'OS
■ Swing
– réimplémente tous les widgets en simulant les look & feel natifs
=> look & feel indépendant de l'OS
=> comportement (à peu près) homogène qq soit l'OS
– architecture logicielle plus sophistiquée
– bien plus puissant !
Page 67 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Architecture Swing
■ Swing est inspiré du modèle MVC
– Model : données de l'application
– View : représentation visuelle
– Controller : gestion des entrées
source: enode.com
Page 68 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Architecture Swing
■ Swing est inspiré du modèle MVC
– Model : données de l'application
– View : représentation visuelle
– Controller : gestion des entrées
■ But de MVC
– mieux structurer les applications
– représentations multi-vues
• un modèle peut être associé à plusieurs vues source: enode.com
• la synchronisation est implicite
■ Remarques
– en pratique V est fortement lié à C
– plusieurs variantes de MVC !
Page 69 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Architecture Swing (2)
■ "Separable Model Architecture"
– View et Controller regroupés dans un UIComponent
– Model : reste séparé
■ "Pluggable Look and Feel"
– chaque JComponent Swing encapsule un UIComponent
– les UIComponent peuvent être changés dynamiquement par le UIManager
Page 70 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Architecture Swing (3)
■ Modèles et multi-vues
– (la plupart des) JComponent Swing créent implicitement un Modèle
– qui peut être "exporté" et partagé avec un autre JComponent
■ Exemple
– JSlider et JScrollbar : même modèle BoundedRangeModel
– mise commun du modèle => synchronisation automatique
Page 71 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Exemple
Dans l’API de JSlider et JScrollBar :
public BoundedRangeModel getModel();
public void setModel(BoundedRangeModel);
Changer le modèle du slider et du scrollbar :
JSlider slider = new JSlider();
BoundedRangeModel myModel = new DefaultBoundedRangeModel( ) {
public void setValue(int n) {
System.out.println(“SetValue: “+ n);
super.setValue(n);
}
});
slider.setModel(myModel);
scrollbar.setModel(myModel);
On peut aussi ignorer l’existence des modèles :
JSlider slider = new JSlider();
int value = slider.getValue();
// cohérent car dans l’API de JSlider :
public int getValue() {return getModel().getValue(); }
Page 72 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Pluggable Look and Feel
Java Metal
public static void main(String[ ] args) {
try {
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) { }
//Create and show the GUI...
.....
}
Windows
UIManager.setLookAndFeel(
“com.sun.java.swing.plaf.windows.WindowsLookAndFeel”
);
Page 73 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Une variante de MVC
source: Sun
Page 74 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Graphics2D
■ Couche graphique évoluée
– plus sophistiquée que Graphics
■ Quelques caractéristiques
– système de coordonnées indépendant du type de sortie (écran, imprimante)
– et transformations affines : translations, rotations, homothéties
• package java.awt.geom
– transparence
• AlphaComposite, BITMASK , OPAQUE, TRANSLUCENT ...
– Composition
– Paths et Shapes
– Fonts et Glyphs
– etc... (voir démo Java2D de Sun)
Page 75 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Pour en savoir plus
■ Site pédagogique de l’UE INF224
– http://www.telecom-paristech.fr/~elc/cours/inf224.html
■ Pour aller plus loin : UEs liées à INF224
– IGR201: Développement d'applications interactives 2D, 3D, Mobile et Web
– IGR203: Interaction Homme-Machine
Page 76 Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech