interfaces graphiques Java Swing
Page 1
Toolkits graphiques Java
Il y en a trois !
– AWT Components, obsolète
– Swing supporté par Oracle (autrefois Sun)
Swing repose sur AWT
– mais Swing != AWT !
– SWT libre, initié par IBM / Eclipse
– tous (+ ou -) multi-plateformes
J F C Les classes Swing font partie d un ensemble plus vaste de classes pour les IHM qui a été appelé les Java Fondation Classes. Les JFC contiennent : java.awt, javax.swing, le package java.awt.geom pour dessiner du 2D, java.awt.dnd pour le drag and drop, javax.accessibility pour développer des applications adaptées aux personnes handicapées, javax.swing.plaf pour modifier le look and feel, etc.
Page 2
Source: documentation IBM
Composants Swing
Page 3
Interacteurs
Page 4
Boutons
JButton
JCheckbox : choix idépendants
JRadioButton : choix exclusif : cf. ButtonGroup
Source: documentation Java Oracle
Page 5
Texte
JTextField
JPasswordField
Page 6
JTextArea : texte simple multilignes
Ascenseur : cf. JScrollPane
JEditorPane : texte avec styles compatible HTML et RTF
Conteneurs
JPanel: conteneur générique
...
JScrollPane: avec ascenseurs intégrés
JSplitPane: avec « diviseur » intégré
Page 7
Conteneurs
JToolBar: barre d’outils (sous la barre de menus)
JTabbedPane: onglets
JTree
JTable
Page 8
Conteneurs spécifiques
JInternalFrame
à placer dans un JDesktopPane qui joue le rôle de bureau virtuel
JLayeredPane permet de superposer des composants
voir aussi JRootPane présenté plus loin
JDesktopPane hérite de JLayeredPane
Page 9
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
– généralement temporaire :
• bloque l’interaction, impose à l’utilisateur de répondre
Page 10
Fenêtres
JRootPane implicitement créé
– par JApplet, JDialog, JFrame
– et JInternalFrame
Page 11
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
Applets
Page 13
Menus
Page 14
Applet = composant de premier niveau
– pour les applications dans pages Web
raccourci clavier (accelerator)
mnémonique
Arbre d’instanciation
Arbre d’instanciation
– arbre de filiation des instances de composants graphiques
Page 15
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
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
Arbre d’instanciation
Objet de plus haut niveau de l’arbre
– JFrame ou JApplet
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( ) – frame.setVisible(true)
// calcul récursif des positions et des tailles // fait apparaître la fenêtre
Page 18
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(); setVisible(true); // fait apparaître l’interface
// calcule la disposition spatiale
} }
Page 19
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
Evénements
Evénements
– envoyés à l’application ciblée – à chaque action élémentaire de l’utilisateur
Page 21
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 fonction main() dans le cas de Java
Page 22
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
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
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 – FocusEvent – etc.
fermeture des fenêtres .... focus clavier (= où vont les caractères tapés au clavier)
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
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
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
Observateurs d’événements
Exemple : MouseEvent
– Evénement : MouseEvent
– Listener : MouseListener – Méthodes :
• mouseClicked(MouseEvent) • mouseEntered(MouseEvent) • mouseExited(MouseEvent) • mousePressed(MouseEvent) • mouseReleased(MouseEvent)
– Listener : MouseMotionListener – Méthodes :
• mouseDragged(MouseEvent)
• mouseMoved(MouseEvent)
Remarque
– toutes les méthodes doivent être implémentées – car les Listeners sont des interfaces (au sens du langage Java)
Publicité
Page 28
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
Exemple : version 1
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame { JButton button;
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
class Ecoute implements ActionListener { // méthode appelée quand on active le bouton public void actionPerformed(ActionEvent e) {
System.out.println("Done!");
button = new JButton ("Do It!"); add(button);
} }
// créer et associer un ActionListener Ecoute elc = new Ecoute(); button.addActionListener(elc);
Problème ?
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
} }
Page 30
Exemple : version 1
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame { JButton button; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
button = new JButton ("Do It!"); add(button);
// créer et associer un ActionListener Ecoute elc = new Ecoute(); button.addActionListener(elc);
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
} }
Page 31
class Ecoute implements ActionListener { public void actionPerformed(ActionEvent e) {
System.out.println("Done!");
label.setText("Done!"); // ne compile pas !
} }
Problème : communication entre objets
– comment le Listener peut-il agir
sur les composants graphiques ?
Exemple : version 1
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame { JButton button; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
button = new JButton ("Do It!"); add(button);
// créer et associer un ActionListener Ecoute elc = new Ecoute(this); button.addActionListener(elc);
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
} }
Page 32
class Ecoute implements ActionListener { BipBip mainWin;
public Ecoute (BipBip mainWin) {
this.mainWin = mainWin;
}
public void actionPerformed(ActionEvent e) {
System.out.println("Done!");
mainWin.label.setText("Done!");
} }
Solution
– le Listener doit conserver une
référence vers la partie graphique
– solution flexible mais lourde...
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 ne peut « hériter » de façon multiple
que des spécifications (i.e. des interfaces)
Page 33
Exemple : version 2
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame
implements ActionListener {
JButton button; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
public void actionPerformed(ActionEvent e) {
label.setText("Done!");
}
} // fin de la classe BibBip
add(button = new JButton ("Do It"));
// BibBip est à la fois un JFrame et un Listener button.addActionListener(this);
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
Remarque
– actionPerformed() à accès à label car c’est une méthode d’instance de BibBip
Autre problème ?
}
Page 34
Exemple : version 2
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame
implements ActionListener {
JButton button; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
add(button = new JButton ("Do It"));
public void actionPerformed(ActionEvent e) {
label.setText("Done!");
}
} // fin de la classe BibBip
// BibBip est à la fois un JFrame et un Listener button.addActionListener(this);
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
Problème : plusieurs boutons
– comment avoir plusieurs comportements avec un seul Listener ?
}
Page 35
Exemple : version 2
import javax.swing.*; import java.awt.event.*;
public class BipBip extends JFrame
implements ActionListener {
JButton doIt, close; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
add(doIt = new JButton ("Do It")); add(close = new JButton ("Close"));
doIt.addActionListener(this); close.addActionListener(this);
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
}
Page 36
public void actionPerformed(ActionEvent e) {
if (e.getSource() == doIt)
label.setText("Done!");
else if (e.getSource() == close)
System.exit(0);
} }
Solution
– distinguer les boutons grâce à
• getSource() ou • getActionCommand()
– la 1ere solution est plus sûre
– peu adapté si beaucoup de
commandes
Avantages et inconvénients
Version 1
– plus souple :
autant de listeners que l'on veut
– mais lourd et peu concis :
on multiplie les objets et les lignes de code
Version 2
– plus simple mais limité :
on ne peut avoir qu'une seule méthode actionPerformed()
– peu adapté si beaucoup de
commandes
Page 37
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
Combinent les avantages des 2 solutions
précédentes
– souplesse sans la lourdeur
Page 38
Exemple : version 3
import javax.swing.*; import java.awt.event.*;
BipBip extends JFrame { JButton doIt, close; JLabel label = new JLabel();
public static void main(String argv[ ]) {
new BipBip();
}
public BipBip() {
class DoItListener implements ActionListener { public void actionPerformed(ActionEvent e) {
label.setText("Done!");
} }
class CloseListener implements ActionListener { public void actionPerformed(ActionEvent e) {
System.exit(0);
} }
add(doIt = new JButton ("Do It")); add(close = new JButton ("Close"));
} // fin de la classe BibBip
doIt.addActionListener(new DoItListener( )); close.addActionListener(new CloseListener( ));
Remarque
setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); setVisible(true);
– actionPerformed() à accès à label car DoItListener est une classe imbriquée de BibBip
}
Page 39
Synthèse
Page 40
Remarques
Remarques
– les classes imbriquées peuvent également servir à encapsuler l’implémentation
– le terme exact est classes internes (inner classes en Anglais)
Page 41
Classes imbriquées anonymes
Publicité
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
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 43
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 44
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
Page 45
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++
Page 46
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 47
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Scribble : 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 48
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Scribble : dessin dans une applet
....(suite)....
// 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 49
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Scribble : dessin dans une applet
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 50
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Avec les 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 51
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Avec les classes imbriquées
....(suite)....
addMouseMotionListener( new MouseMotionAdapter ( ) {
public void mouseDragged(MouseEvent e) {
// même code que dans la précédente version ....
}
} );
// ajouter un bouton qui efface tout JButton b = new JButton("Clear"); 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 52
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
Page 53
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 54
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()
– car 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 55
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
– les repaint() sont compactés (un seul paint())
Page 56
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Divers
Divers
– Appeler revalidate() dans certains cas de changements de taille
– Taille des bords : getInsets()
– Opacité des widgets
• certains composants sont opaques, d’autres sont transparents
• setOpaque() => composant opaque (et plus rapide)
Page 57
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
JFileChooser
JFileChooser chooser = new JFileChooser();
Publicité
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 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 !
Page 60
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
Page 61
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 62
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 63
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 64
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 65
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 66
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 67
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Autres toolkits graphiques Java
AWT Components
– "Abstract Widget Toolkit"
– 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 68
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 69
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 70
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 • la synchronisation est implicite
source: enode.com
■ Remarques
– en pratique V est fortement lié à C
– plusieurs variantes de MVC !
Page 71
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 72
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 73
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 74
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 75
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
Une variante de MVC
Page 76
Programmation événementielle et interfaces graphiques - Eric Lecolinet – Telecom ParisTech
source: Sun