Interfaces graphiques Java Swing

Java Programming · notes

Voir tous les documents en programmation

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