Chapitre 5:
Programmation événementielle
& interfaces graphiques Java Swing
Mohammed OUANAN
Generalities sur AWT
♦ AWT est une interface utilisateur offrant un ensemble de classes et de fonctions pour le
développement des interfaces graphiques
♦ AWT fut introduite dès java 1.0. Depuis Java 1.2, SWING a très largement remplacé AWT
♦ AWT regroupe toutes les fonctionnalités communes à tous les systèmes graphiques pour la
manipulation des objets GUI
♦ AWT fait appel à l’afficheur natif du système local pour dessiner les composantes graphiques
AWT n’est pas totalement indépendante de l’OS:
- Avantage: rendement graphique plus rapide
- Inconvénients: apparence différente d’un système à l’autre
Page 2
Services fouirnit par AWT
5 services sont proposés au programmeur :
1. Un ensemble de composants GUI usuels (control/widgets)
2. La notion d’objets Containers qui fournissent un support et un contexte
aux composants GUI utilisés
3. Des gestionnaires d’affichage permettant de positionner les composants
GUI ajoutés à un container
4. Un support basique de fonctions de dessin tels : dessin d’un trait,
rectangle, polygones…
5. Un gestionnaire d’événement qui permet au programmeur de déclarer le
événements que l’application doit gérer.
Page 3
Swing vs Awt
Les classes de la bibliothèque AWT sont écrites en code natif du système qui accueille java. On
parle alors de composants lourds. Quoiqu’elle présente l’avantage d’être plus rapide en
affichage
Les composants légers sont, quant à eux, des composants écrits entièrement en Java. La
bibliothèque Swing n’offre que des composants légers
Swing, en fait, triche un peu. Ses composants dérivent pour la plupart de Component de AWT
ce qui assure en fait le lien avec le système d’affichage natif de la plate-forme utilisée
Swing garantit une apparence uniforme de l’application entre les différentes plates-formes
Swing possède une fonctionnalité assez avancé, appelée le “pluggable look and feel “ qui
signifies que l’apparence de l’interface utilisateur peut être modifié dynamiquement pou
s’adapter aux habitudes de l’utilisateur travaillant sur une plateforme et OS différents
La bibliothèque Swing a été conçue pour permettre une conversion « relativement » aisé
des applications écrites à l’aide d’awt. Dans bien des cas il suffit d ’ajouter un ‘ J ’ au
nom des classes des composants awt
Page 4
Composants Swing
Source: documentation IBM
Page 5
Interacteurs
Page 6
Boutons
JButton JCheckbox : JRadioButton :
choix idépendants choix exclusif : cf. ButtonGroup
Source: documentation Java Oracle
Page 7
Texte
JTextField
JPasswordField
JTextArea :
texte simple multilignes
Ascenseurs :
JScrollPane
JEditorPane : texte avec styles
compatible HTML et RTF
Page 8
Conteneurs
JPanel: conteneur générique
...
JSplitPane:
JScrollPane: avec « diviseur » intégré
avec ascenseurs intégrés
Page 9
Conteneurs
JToolBar: barre d’outils
(sous la barre de menus)
JTabbedPane:
onglets
JTree
JTable
Page
10
Fenêtres
JFrame : fenêtre principale de l’application
JDialog : fenêtre secondaire
• dépendante de la JFrame (en théorie pas d’iconification séparée, toujours au dessus)
JDialog modal : bloque l’interaction => l’utilisateur de répondre
Page 12
Fenêtres
Créent des paneaux intermédiaires
• ContentPane : conteneur où on ajoute
les composants graphiques
• GlassPane : conteneur transparent
superposé (pour usages avancés)
Page 13
Boîtes de dialogue prédéfinies
JFileChooser JColorChooser
Peuvent être créés :
• comme boîtes de dialogue
• ou comme conteneurs
JOptionPane (multiples variantes)
Page 14
Menus
raccourci
clavier
(accelerator)
mnémonique
Page 15
Arbre d’instanciation
Arbre d’instanciation
• arbre de filiation des instances de composants graphiques
Page 16
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 17
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 18
Arbre d’instanciation
JFrame = objet de plus haut niveau
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
Ne pas oublier d’appeler :
• [Link]( ) // calcul récursif des positions et des tailles
• [Link](true) // fait apparaître la fenêtre
Page 19
Exemple : version 0
import [Link].*;
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 : avant version 5
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Bib Bip");
pack(); // calcule la disposition spatiale
setVisible(true); // rend l’interface visible
}
}
Page 20
Exemple : version 0
Notes :
• package [Link]
• 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
[Link]() a été redéfini dans les versions ultérieure de Java
Page 21
Evénements
Evénements
• envoyés à l’application ciblée
• à chaque action élémentaire de l’utilisateur
Page 22
Boucle de gestion des événements
Boucle infinie qui
• récupère les événements
• notifie les composants graphiques
Lancée automatiquement
• à la fin de la méthode main() dans le cas de Java
Page 23
Evénements Java
Evénements AWT et Swing
• objets correspondant à des catégories d’évenements
• les principaux héritent de [Link]
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 24
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 25
Détecter les événements
Principe : patron Observateur / Observé
• Associer un ou des observateurs aux objets observés
• Les observateurs sont notifiés automatiquement
• quand une certaine condition se produit sur un observé
source: Wikipedia
Page 26
Event listeners
A chaque classe d’événement correspond une classe d’Event Listener
(sauf cas particuliers)
Exemple : ActionEvent
• Evénement : ActionEvent
• Listener : ActionListener
• Méthode : actionPerformed(ActionEvent)
Page 27
Event listeners
Exemple : MouseEvent
• Evénement : MouseEvent
• Listener : MouseListener
• Méthodes : • Listener : MouseMotionListener
• mouseClicked(MouseEvent) • Méthodes :
• mouseEntered(MouseEvent) • mouseDragged(MouseEvent)
• mouseExited(MouseEvent) • mouseMoved(MouseEvent)
• mousePressed(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
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 [Link].*;
import [Link].*;
public class BipBip extends JFrame {
JButton button;
public static void main(String argv[ ]) {
new BipBip(); class Ecoute implements ActionListener {
} // méthode appelée quand on active le bouton
public void actionPerformed(ActionEvent e) {
public BipBip() {
button = new JButton ("Do It"); [Link]("Done!");
}
add(button);
}
// créer et associer un ActionListener
Ecoute elc = new Ecoute();
[Link](elc);
setDefaultCloseOperation(EXIT_ON_CLOSE); Inconvénients ?
pack();
setVisible(true);
}
}
Page 30
import [Link].*;
import [Link].*;
public class BipBip extends JFrame {
JButton button;
JLabel label = new JLabel();
public static void main(String argv[ ]) { class Ecoute implements ActionListener {
new BipBip(); public void actionPerformed(ActionEvent e) {
}
[Link]("Done!");
public BipBip() { [Link]("Done!"); // ne compile pas !
button = new JButton ("Do It"); }
add(button); }
Ecoute elc = new Ecoute();
[Link](elc);
Communication entre objets
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); comment le Listener peut-il agir
setVisible(true); sur les composants graphiques ?
}
}
Page 31
class Ecoute implements ActionListener {
import [Link].*;
BipBip bipbip;
import [Link].*;
public class BipBip extends JFrame { public Ecoute (BipBip bipbip) {
JButton button; [Link] = bipbip;
JLabel label = new JLabel(); }
public static void main(String argv[ ]) {
new BipBip(); public void actionPerformed(ActionEvent e) {
} [Link]("Done!");
[Link]("Done!");
public BipBip() { }
button = new JButton ("Do It"); }
add(button);
Ecoute elc = new Ecoute(this);
[Link](elc); Solution
setDefaultCloseOperation(EXIT_ON_CLOSE);
• le Listener a une référence
pack(); vers la partie graphique
setVisible(true);
} • solution flexible mais lourde
}
Page 32
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
• restreint avec Java : on peut « hériter » de plusieurs interfaces
• (mais pas de plusieurs classes)
Page 33
Exemple : version 2
import [Link].*;
import [Link].*;
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") );
add(label)
// BibBip est à la fois un JFrame et un Listener
[Link](this);
setDefaultCloseOperation(EXIT_ON_CLOSE);
actionPerformed() à accès à label
pack();
setVisible(true); car c’est une méthode d’instance
} de BibBip
public void actionPerformed(ActionEvent e) {
[Link]("Done!"); Inconvénients ?
}
}
Page 34
import [Link].*;
import [Link].*;
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") );
// BibBip est à la fois un JFrame et un Listener
[Link](this);
setDefaultCloseOperation(EXIT_ON_CLOSE); Plusieurs boutons ?
pack();
setVisible(true); comment avoir plusieurs comportements
} avec un seul Listener ?
public void actionPerformed(ActionEvent e) {
[Link]("Done!");
}
}
Page 35
import [Link].*; // suite de la classe BipBip
import [Link].*;
public void actionPerformed(ActionEvent e) {
public class BipBip extends JFrame if ([Link]() == doIt)
implements ActionListener { [Link]("Done!");
JButton doIt, close;
else if ([Link]() == close)
JLabel label = new JLabel();
[Link](0);
public static void main(String argv[ ]) { }
new BipBip(); } // fin de la classe !
}
public BipBip() {
add(doIt = new JButton("Do It"));
add(close = new JButton("Close")); On peut distinguer les boutons
[Link](this);
via getSource()
c [Link](this);
Autre solution getActionCommand()
setDefaultCloseOperation(EXIT_ON_CLOSE); (moins sûre car dépend des noms)
pack();
setVisible(true);
}
Page 36
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
méthode actionPerformed()
• peu concise :
on multiplie les objets et les lignes de code • peu adaptée si beaucoup de
commandes
Page 37
Classes imbriquées
Classes définies à l’intérieur d’une autre classe
• ont accès aux variables d’instance
des classes les contenant
• rappel : pas en C++ !
Avantages des 2 solutions précédentes
• souplesse sans la lourdeur !
Notes
• le terme exact est inner classes
• elles peuvent être static
(sert à structurer en sous-parties)
Page 38
Exemple : version 3
import [Link].*; class DoItListener implements ActionListener {
import [Link].*; public void actionPerformed(ActionEvent e){
[Link]("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){
} [Link](0);
}
public BipBip() {
}
add( doIt = new JButton("Do It") );
add( close = new JButton("Close!") ); } // fin de la classe BibBip
[Link](new DoItListener( ));
[Link](new CloseListener( ));
actionPerformed() à accès à label
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); car DoItListener est une
setVisible(true);
} classe imbriquée de BibBip
Page 39
Synthèse
Page 40
Disposition spatiale
Les LayoutManagers
• calculent automatiquement la disposition spatiale des enfants des conteneurs
A chaque conteneur est associé un LayoutManager
• qui dépend du type de conteneur
• qui peut être changé par la méthode : setLayout()
Pour faire le calcul "à la main"
• à éviter sauf cas particuliers : setLayout(null)
Page 41
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 taille du texte
• langues orientales : texte ~1/3 plus petit que l'anglais
• français, allemand : texte ~1/3 plus grand que l'anglais
Adaptativité
• les composants graphiques se retaillent automatiquement
• quand l'utilisateur retaille les fenêtres
Page 42
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 43
Principaux LayoutManagers
BorderLayout
• défaut des JFrame et JDialog
• disposition de type points cardinaux
• via constantes: [Link], EAST, NORTH, SOUTH, WEST
• retaille automatiquement les enfants
Page 44
BorderLayout
import [Link].*;
public class EssaiBorderLayout extends Frame
{
private Button b1,b2,b3,b4, b5;
public EssaiBorderLayout() {
setLayout(new BorderLayout());
b1 = new Button ("Nord"); b2 = new Button ("Sud");
b3 = new Button ("Est"); b4 = new Button ("Ouest");
b5 = new Button ("Centre");
[Link](b1, [Link]);
[Link](b2 , [Link]);
[Link](b3, [Link]);
[Link](b4, [Link]);
[Link](b5, [Link]);
}
public static void main (String args []) {
EssaiBorderLayout essai = new EssaiBorderLayout();
[Link] (); [Link](true) ;
}}
Page 45
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
import [Link].*;
public class AppliGridLayout extends Frame
{
public AppliGridLayout()
{
super("AppliGridLayout");
[Link](new GridLayout(3,2));
for (int i = 1; i < 7; i++)
add(new Button([Link](i)));
[Link]();
[Link]();
}
public static void main(String args[])
{
AppliGridLayout appli = new
AppliGridLayout();
}
}
Page 46
Principaux LayoutManagers (2)
GridBagLayout
• grille + contraintes spatiales
• les enfants n'ont pas tous la même taille
• spécification par des GridBagConstraints
Page 47
Principaux LayoutManagers (3)
CardLayout
• empile les enfants (et les met à la même taille)
• usage typique: onglets
BoxLayout
• disposition verticale ou horizontale
• exemple :
[Link](new BoxLayout(panel, BoxLayout.Y_AXIS));
SpringLayout
• contraintes entre les bords des enfants
• usage typique : formulaires
Page 48
Mise en forme complexe
super("AppliComplexeLayout");
setLayout(new BorderLayout());
Panel pnorth = new Panel();
[Link](b1); [Link](b2);
[Link](b3); [Link](b4);
[Link](pnorth,[Link]);
Panel pcenter = new Panel();
[Link](new GridLayout(2,2));
[Link](gr1); [Link](gr2);
[Link](gr3); [Link](gr4);
[Link](pcenter,[Link]);
Panel psouth = new Panel();
[Link](new FlowLayout());
[Link](ch); [Link](tf);
[Link](psouth, [Link]);
Page 49
Classes imbriquées anonymes & lambdas
public class BipBip extends JFrame {
JLabel label = new JLabel();
public BipBip() {
var doIt = new JButton("Do It"); // var = inférence de type (comme auto en C++)
add(doIt);
[Link]( new ActionListener( ) { // sous-classe anonyme de ActionListener
public void actionPerformed( ActionEvent event ) {
[Link]("Done!");
}
} );
OU : // expression lambda
[Link]( (ActionEvent event) -> [Link]("Done!") );
OU :
[Link]( (event) -> [Link]("Done!") ); // si le type peut etre inféré
OU :
[Link]( event -> [Link]("Done!") ); // si un seul argument
}
......
Page 50
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) {
[Link]("Done!");
}
});
......
Page 51
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([Link]); // FAUX : pas le bon « close »
[Link](close); // ERREUR : pas le bon « this »
[Link](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 52
Compléments sur les constructeurs
abstract class MyButton extends JButton implements ActionListener {
public MyButton (String name, Icon icon) {
super(name, icon);
........
}
public MyButton (String name) { Un constructeur peut en appeler un autre !
this(name, null);
} Note : en C++11:
• MyButton(string name) : MyButton(name, nullptr) {}
} • on pourrait aussi utiliser les paramètres par défaut
abstract class Toto {
Constructeur de classe
static {
• Pour initaliser des variables de classes
.......
• Pas d'équivalent direct en C++
}
Page 53
Dessin
import [Link].*;
import [Link].*;
import [Link].*;
class Canvas extends JPanel {
private int last_x, last_y;
Canvas() {
setBackground([Link]);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
last_x = [Link]();
last_y = [Link]();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
int x = [Link]();
int y = [Link](); si on utilisait MouseListener ou
var g = getGraphics(); MouseMotionListener il faudrait implémenter :
[Link](last_x, last_y, x, y);
last_x = x; public void mouseReleased (MouseEvent e) { }
last_y = y; public void mouseClicked (MouseEvent e) { }
} public void mouseEntered (MouseEvent e) { }
}); public void mouseExited( MouseEvent e) { }
}
Page 54
Dessin
// fin de la classe Canvas public class Scribble1 extends JFrame {
void clear() { public static void main(String argv[]) {
var g = getGraphics(); new Scribble1();
[Link]([Link]); }
[Link](0, 0,
getSize().width, Scribble1( ) {
getSize().height); var canvas = new Canvas();
} var clear = new JButton("Clear");
} [Link](e -> [Link]());
add([Link], canvas);
add([Link], clear);
setTitle("Scribble");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setMinimumSize(new Dimension(400, 400));
pack();
setVisible(true);
}
}
Problème ?
Page 55
Persistance de l’affichage
Problème : l’affichage du dessin n’est pas persistant
• dessin effacé si on retaille, iconifie, etc.
• les méthodes des listeners ne devraient pas dessiner !
si on retaille...
Page 56
Modèle "damaged / repaint"
repaint()
paintComponent()
Principe
Les listeners :
• sauvegardent les opérations sans afficher
• notifient le toolkit en appelant repaint
La méthode paintComponent repaint le widget (et le dessin !)
Page 57
Persistance de l’affichage
class Canvas extends JPanel
{
private ArrayList<Point> points = new ArrayList<Point>();
Canvas() {
setBackground([Link]);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
[Link](new Point([Link](), [Link]()));
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
[Link](new Point([Link](), [Link]()));
repaint();
}
}); protected void paintComponent(Graphics g) {
} [Link](g);
for (int k = 0; k < [Link]()-1; ++k) {
void clear() { [Link]((int)[Link](k).getX(),
[Link](); (int)[Link](k).getY(),
repaint(); (int)[Link](k+1).getX(),
} (int)[Link](k+1).getY());
}
}
}
Page 58
Notes
Swing vs. AWT
• avec AWT redéfinir la méthode paint()
• avec Swing, paint() appelle :
• paintComponent() puis paintBorder() puis paintChildren()
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() rend le composant opaque
Page 59
JFileChooser
Ouvre la boîte de dialogue et bloque l’interaction (dialogue modal) :
int returnVal = [Link](parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
[Link]("You chose to open this file: "
+ [Link]().getName());
}
Filtre
JFileChooser chooser = new JFileChooser();
var filter = new FileNameExtensionFilter("JPG & GIF", "jpg", "gif");
[Link](filter);
Page 60
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: [Link]
Page 61
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: [Link]
• la synchronisation est implicite
En pratique
• V fortement lié à C
• plusieurs variantes de MVC !
Page 62
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 63
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 64
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) {
[Link](“SetValue: “+ n);
[Link](n);
}
});
[Link](myModel);
[Link](myModel);
On peut aussi ignorer l’existence des modèles :
JSlider slider = new JSlider();
int value = [Link]();
// cohérent car dans l’API de JSlider :
public int getValue() {return getModel().getValue(); }
Page 65
Autres visions de MVC
A plus haut niveau, autre vision possible
• Controllers = Listeners Swing
(Controleurs de haut niveau)
• Views = Components Swing
(incluant des Controleurs de bas niveau)
• Models
Vision Web
• cf. illustration
Autres variantes
• model–view–adapter (MVA)
• model–view–presenter (MVP)
• model–view–view model (MVVM)
• hierarchical model–view–controller (HMVC)
Page 66
Pluggable Look and Feel
Java Metal
public static void main(String[ ] args) {
try {
[Link](
[Link]());
} catch (Exception e) { }
//Create and show the GUI...
.....
}
Windows
[Link](
“[Link]”
);
Page 67
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 [Link]
• transparence
• AlphaComposite, BITMASK , OPAQUE, TRANSLUCENT ...
• Composition
• Paths et Shapes
• Fonts et Glyphs
• etc... (voir démo Java2D de Sun)
Page 68
Pour en savoir plus
Site pédagogique de l’UE INF224
• [Link]
UEs liées à INF224
• IGR201: Développement d'applications interactives 2D, 3D, Mobile et Web
• IGR203: Interaction Homme-Machine
Page 69