introduction à la boîte à outils swt : the standard widget toolkit
Post on 18-Dec-2014
9.539 Views
Preview:
DESCRIPTION
TRANSCRIPT
Développement de clients riches : Plateforme Eclipse
Mickaël BARON - 2007 (Rév. Janvier 2009) mailto:baron.mickael@gmail.com ou mailto:baron@ensma.fr
(SWT) - Standard Widget Toolkit
Chapitre 2 : BoChapitre 2 : Boîîtes tes àà outilsoutils
2SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Creative Commons
Contrat Paternité
Partage des Conditions Initiales à l'Identique
2.0 France
http://creativecommons.org/licenses/by-sa/2.0/fr
Licence
3SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Organisation du cours sur la boîte à outils SWT
� Evolution des boîtes à outils pour Java
� Conteneurs
� Composants de type Control
� Agents de placement
� Gestion des événements
� Dessiner avec Graphical Context
� Les boîtes de dialogue (Message, Couleur, …)
� Les indispensables (appel SWT dans des Threads …)
� Co-habitation entre SWT et Swing
4SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Evolution des boîtes à outils Java
� La bibliothèque AWT (Abstract Window Toolkit)
� BAO historique de Java depuis le JDK 1.0 mais toujours utilisable (souvent utilisée directement pour les Applets)
� Tous les composants sont implémentés à partir du sous-ensemble « portable » des composants natifs des systèmes hôtes (HeavyweightComponent)
� L’affichage et le comportement de l’IHM sont fortement liés au système hôte
Système graphique : X11, Windows, etc.
Peer
AWT
Application Java
Machine virtuelle
Tracé graphique
Fournit un ensemble d’interface permettant aux composants graphiques
d’être représentés à l’écran
5SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Evolution des boîtes à outils Java
� La bibliothèque Swing
� BAO considérée comme standard en Java 2 Platform (depuis le JDK 2)
� Tous les composants sont implémentés directement sans faire appel
aux composants natifs du système hôte (Lightweight Components)
� L’affichage et le comportement de l’IHM sont indépendants du
système hôte et ne dépendent que du programmeur ou de l’utilisateur
(Look and Feel)
Système graphique : X11, Windows, etc.
Peer
AWT
Application Java
Machine virtuelle Swing
Tracé graphique
6SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Boîte à outils SWT
� SWT : Standard Widget Toolkit
� Bibliothèque développée par IBM pour le projet Eclipse
� www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html
� Distribuée librement pour le développement de plug-ins ou d’application stand-alone
� Fournit des composants de base (bouton, label, …)
� Fournit des composants plus complexes avec JFace
� Fournit un modèle pour la gestion des événements identique à celui utilisé par AWT et Swing (abonnement)
7SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Boîte à outils SWT
Système graphique : X11, Windows, etc.
SWT.dll, SWT.so, …
SWT
Application Java
Machine virtuelle
Tracé graphique
� SWT fournit des techniques d’implémentation de bas niveau
� SWT procure des composants graphiques natifs d’une manière indépendante de l’OS
� Combinaison de classes Java et JNI spécifiques à chaque plateforme
� JNI utilisé pour invoquer le système d’exploitation
8SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Comparaison Swing/SWT
� Performance : même si SWT s’appuie sur des composants
natifs il y a des cas particuliers où Swing est plus rapide
� Affichage de très grand nombre d’information : JTable Swing plus
rapide qu’un TextViewer SWT/JFace
� Composants natifs = meilleure réactivité et rapidité de chargement
� Portabilité : avec SWT nécessité d’utiliser des bibliothèques
natives alors que pour Swing aucune contrainte
� Pour SWT installation des bibliothèques
� Pour Swing déjà pré-installé
9SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Comparaison Swing/SWT (suite)
� Look : SWT ne permet pas de modifier l’apparence des
composants
� Pour SWT respect des habitudes de l’utilisateur
� Pour Swing possibilité de s’adapter à un type d’utilisateur (un look
cartoon pour les enfants)
� Reproche à Swing son aspect non professionnel (à voir)
� Développement : SWT nécessite de libérer les ressources
pas pour Swing
� Pour SWT de nombreux composants adapté (assistant par exemple)
� Swing n’est pas en reste avec les composants SwingLabs
� Pour Swing plus de documentations pour l’aide au développement
� Pour SWT moins d’exemples mais ça arrive …
10SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
SWT : les ressources …
� Le site de la fondation Eclipse
� La page d’accueil sur SWT (www.eclipse.org/swt)
� Un ensemble d’exemples (www.eclipse.org/swt/snippets)
� Des articles de la fondation Eclipse� www.eclipse.org/articles/Article-SWT-images/graphics-resources.html
� www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
� www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html et 2
� Et pleins d’autres encore …
� Des supports de cours et des exemples
� www.labo-sun.com/resource-fr-essentiels-903-0-java-gui-swt-creer-des-interfaces-
graphiques-performantes.htm
� www.java2s.com/Code/Java/SWT-JFace-Eclipse/CatalogSWT-JFace-Eclipse.htm
11SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comPrincipaux composants graphiques de SWT
� Fenêtres
� Les fenêtres de base et les boîtes de dialogue
� Composants
� Les principaux composants d’interaction : boutons, menus, Tree, Table, Scale, …
� Les composants JFace apporteront une vision MVC des composants
� Conteneurs
� Composants spécifiques (parfois invisibles) qui servent à contenir des composants et/ou Conteneurs
� Les fenêtres sont des conteneurs
� Agents de placements
� Ce sont des objets qui servent à placer des composants dans un conteneur
12SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Exemple : le compteur file rouge
� Le compteur …
� Un bouton et un entier sont affichés dans une fenêtre
� Lorsque l’utilisateur appuie sur le bouton, l’entier est incrémenté d’une
unité puis affiché
� Composants graphiques visibles
� Une fenêtre principale
� Un bouton que l’utilisateur peut déclencher
� Une zone de texte non modifiable par l’utilisateur
� Réaction aux actions de l’utilisateur
� L’événement « clic sur le bouton » doit incrémenter l’entier et
l’afficher à nouveau
Fenêtre
Bouton
Label
13SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLe compteur : structure des composants
� La fenêtre� Classe : Shell
� Le contenu de la fenêtre� La fenêtre est un conteneur de type Composite� Permet d’y ajouter les autres composants
� Le bouton et la zone de texte� Classes : Button et Label� Ajoutés au conteneur pour pouvoir s’y afficher
Le placement des composants n’est pas encore défini
myShell
Shell
Composite
myLabelmyButton
…
Détail plus tard …
myShellcontient
14SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Le compteur : implémentation
� Étapes de développement
� Récupération du Display
� Création de la fenêtre
� Création des composants
en les ajoutant à la fenêtre
� Dimensionnement de la
fenêtre (optionnel)
� Affichage de la fenêtre
public class Compteur {public Compteur() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");
Button myButton = new Button(myShell,SWT.NONE);myButton.setText("i->i+1");Label myLabel = new Label(myShell, SWT.CENTER);myLabel.setText("i = 0");
myShell.pack();myShell.open();
while(!myShell.isDisposed()) {if (!display.readAndDispatch())
display.sleep();}display.dispose();
}
public static void main (String args[]) {new Compteur();
}}
Détail plus tard …
Compteur.java du projetIntroExamples
15SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLe compteur : résultat de l’affichage …
� Le résultat n’est pas celui espéré …
� Le placement des composants n’a pas été effectué
� Les composants ne sont pas visibles (ils le sont mais leur position et
leur taille sont nulles)
� Il manque un agent de placement de type Layout
� Par défaut il n’y a pas d’agent de placement (null)
16SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Placement d’un composant dans un conteneur
� Une IHM en Java peut avoir plusieurs apparences� La taille et le type de police varient
� Les composants possèdent différentes représentations
� Le placement des composants ne peut se faire de manière absolue
� Utilisation d’agents de placement : « Layout Manager »� Un agent de placement est associé à un conteneur
� Par défaut il n’y a pas d’agent de placement (null) qui est utilisé dans les conteneurs
� L’agent de placement place les composants les uns par rapport aux autres
� de la taille préférée de chacun des composants
� de la place disponible dans le conteneur
� de la politique de placement définie par l’agent de placement
17SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLe compteur : utilisation d’un RowLayout
public class CompteurLayout {public CompteurLayout() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");myShell.setLayout(new RowLayout(SWT.VERTICAL));Button myButton = new Button(myShell,SWT.NONE);myButton.setText("i->i+1");Label myLabel = new Label(myShell, SWT.CENTER);myLabel.setText("i = 0");
myShell.pack();myShell.open();...
}
public static void main (String args[]) {new CompteurLayout();
}}
� Les composants sont placés par le RowLayout� en respectant leur taille préférée
� de haut en bas
� la méthode pack() demande le placement automatique des composants
� Exemple : le compteur agencé avec RowLayout
Le placement est correcte, il faudrait par contre agrandir la taille du bouton en fonction de la
fenêtre
CompteurLayout.java du projet IntroExamples
18SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
public class CompteurLayout2 {public CompteurLayout2() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");myShell.setLayout(new FillLayout(SWT.VERTICAL));Button myButton = new Button(myShell,SWT.NONE);myButton.setText("i->i+1");Label myLabel = new Label(myShell, SWT.CENTER);myLabel.setText("i = 0");myShell.pack();myShell.open();while(!myShell.isDisposed()) {
if (!display.readAndDispatch())display.sleep();
}display.dispose();
}
public static void main (String args[]) {new CompteurLayout2();
}}
Le compteur : utilisation d’un FillLayout
� Les composants sont placés par le FillLayout� de haut en bas (identique au RowLayout sans respect de la taille)
� tous les éléments ont la même ligne
� Exemple : le compteur agencé avec FillLayout
CompteurLayout2.java du projet IntroExamples
19SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Réalisation classique d’une interface graphique
� Étapes de la réalisation sans gestion des événements
� Création d’une fenêtre avec un objet de type Shell
� Création d’un agent de placement et association au conteneur du Shell
� Création d’un composant
� Ajout du composant au conteneur
� Création d’un autre composant
� …
Utilisez le plus possible des conteneurs pour placer
correctement vos composants. C’est gratuit …
20SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Conception d’une interface graphique complexe
� Hiérarchisation des composants en arbre de conteneurs
� Grouper les composants dans les conteneurs (Composite) avec une
politique de placement grâce aux agents de placement
� Grouper de nouveaux les composants obtenus
Ces composants peuvent être définis localement ou bien être des instances d’autres classes qui hériteraient de Composite
21SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Conception d’une interface graphique complexe
� Décomposition des composants de l’application
Button(SWT.PUSH) valider
Composite haut(RowLayout)
Text (SWT.MULTI) myText
Shell(GridLayout)
Button(SWT.PUSH) annuler
Button(SWT.RADIO) sms
Button(SWT.RADIO) email
Composite bas(FillLayout)
bas
haut
myText
22SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
� Exemple : création d’un composant avec du texte un champ
� Création du texte avec la classe Label
� Création du champ avec la classe Text
� Placement dans un Composite� Nouvelle classe LabelText hérite de Composite et pourra ainsi
être utilisée comme composant dans une autre application
Des composants réutilisables
public class CompositeWidgets extends Composite {public CompositeWidgets(Composite parent, String label,
String textf) {super(parent, SWT. NONE);GridLayout myGL = new GridLayout(2, false);this.setLayout(myGL);Label myLabel = new Label(this, SWT. NONE);myLabel.setText(label);Text myText = new Text(this,SWT. BORDER);myText.setText(textf);GridData myGD = new GridData(GridData. FILL_BOTH);myText.setLayoutData(myGD);
}... // Suite dans le prochain transparent
}
CompositeWidgets.java du projet IntroExamples
23SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Des composants réutilisables
� Exemple (suite) : création d’un composant personnalisé� Création d’une fenêtre Shell� Création d’une instance du LabelText et ajout au container de la Shell
public class CompositeWidgets extends Composite {... // Suite dans le précédent transparent
public static void main(String[] argv) {Display display = new Display ();Shell shell = new Shell (display);shell.setLayout(new FillLayout(SWT. VERTICAL));new LabelText(shell, "Saisissez le nom", "");
shell.pack ();shell.open ();while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();}display.dispose ();
}}
CompositeWidgets.java du projet IntroExamples
24SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Des concepts de base
� SWT utilise des ressources du système d’exploitation
� Toutes ressources allouées se doivent d’être libérées� www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html
� Le garbage collector n’est pas capable de libérer la mémoire puisqu’il lui est impossible de connaître l’ordre de libération
� Règle 1 : « if you created it, you dispose it »� Libération explicite des ressources graphiques
� Nécessité de libérer les ressources par la méthode dispose()
Font font = new Font (display, "Courier", 10, SWT.NO RMAL);... // Utilisation de l’objet fondfont.dispose();
Détruire les objets
Font font = ref.getFont();... // Utilisation de l’objet fond
Ne pas détruire les objets
Récupérationd’un objet
Création d’un objet
25SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Des concepts de base
� Règle 2 : « disposing the parent, dispose the children »
� Un composant ne peut pas exister dans le système d’exploitation sans composant parent
� Création du conteneur obligatoirement avec le contenu
� Contrôle du cycle de vie via la relation parent-enfant exprimée via le constructeur
� Si le composant parent est libéré, les composants enfants seront automatiquement libérés
public class Compteur {public Compteur() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");Button myButton = new Button(myShell,SWT.NONE);...
}...
}
A la construction des composants, obligationd’indiquer le conteneur
Les composants non graphiques Font, Color, …ne sont pas des enfants et devront être libérés …
Si myShell libéré tous ces enfants le sont aussi
26SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Le Display
� Rôle et caractéristiques de la classe Display� Effectue la connexion entre l’application Java et le système
d’exploitation hôte
� Fournit le mécanisme de traitement des événements
� Package : org.eclipse.swt.widgets.Display
� Quelques méthodes utiles de la classe Display� static Display getCurrent() ou getDefault() : récupère un Display
� Rectangle getBounds() : récupère la taille de l’écran
� Color getSystemColor(String id) : effectue la relation entre les couleurs de SWT et du système
� boolean readAndDispatch() : transfert les événements du système àl’application, retourne vraie s’il y a encore des événements
� setCursorLocation(int x, int y) : déplace le pointeur de l’écran
27SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Le Display
� La fonction principale de l’objet Display est la gestion de la
boucle principale d’événements
� En comparaison avec la boite à outils Swing où la boucle est
implicite, SWT nécessite de définir explicitement une boucle
� Définition d’une boucle d’événement
public class Compteur {public Compteur() {
...while(!myShell.isDisposed()) {
if (!display.readAndDispatch())display.sleep();
}display.dispose();
}}
readAndDispatch() récupère les événements du système
hôte et les transmet àl’application
Tant que la fenêtre en « vie »
readAndDispatchcontinue àdispatcher
Si readAndDispatch()retourne vraie des
événements sont encore àtraiterSi readAndDispatch()
retourne faux mise en attente jusqu’à l’arrivée de nouveaux événements
28SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Erreurs et Exceptions
� SWT distingue trois types d’exceptions
� SWTError
� Levée lors d’une erreur fatale
� Une erreur irrécupérable
� SWTException
� Levée lors d’une erreur non fatale
� Une erreur récupérable
� Exemple : Invalid thread access
� IllegalArgumentException
� Exception levée lors d’une erreur non fatale
� Un argument fourni est invalide
� Exemple : argument ne peut être null
29SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La hiérarchie des packages SWT
� org.eclipse.swt : package de base qui contient la définition des
constantes (SWT) et des exceptions
� org.eclipse.swt.accessibility : package concernant l’accessibilité
� org.eclipse.swt.awt : package permettant l’intégration de
composants Swing dans SWT
� org.eclipse.swt.browser : package concernant le composant browser
� org.eclipse.swt.custom : composants particuliers (TableTree)
� org.eclipse.swt.dnd : support du Drag&Drop
� org.eclipse.swt.events : pour la gestion des événements
30SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La hiérarchie des packages SWT
� org.clipse.swt.graphics : ensemble de classes pour le graphique
� org.eclipse.swt.layout : agents de placement
� org.eclipse.swt.ole.win32 : gestion OLE pour Windows
� org.eclipse.swt.printing : pour la gestion de l’impression
� org.eclipse.swt.program : exécution d’application sur l’OS
� org.eclipse.swt.widgets : API des composants graphiques
Dans la suite de ce cours nous allons nous intéresser plus
particulièrement aux packages widgets, graphics, events,
layout et awt
31SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La hiérarchie des composants SWT
� Hiérarchie des principaux composants
Control
Widget
Tray
Scrollable
Composite
Menu …
Button Label …
Combo Browser …
Text List Les sous-classes de Control, Scrollable et Composite seront
étudiées dans ce cours
32SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La hiérarchie des composants SWT
� La classe Widget est la classe de plus haut niveau pour les composants graphiques
� Sous-classes de Control� Service : composants fils à une fenêtre avec réaction à enregistrement
à des événements de base (MouseListener, KeyListener, …)
� Exemples : Button, Label
� Sous-classes de Scrollable� Service : composants avec des barres de défilement
� Exemple : List, Text
� Sous-classes de Composite� Service : composants capable de contenir des composants Control
appelés également conteneur
� Exemple : Canvas, Group
33SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La classe Widget
� La classe Widget est la classe de plus haut niveau de la hiérarchie SWT
� Services proposés
� Mécanisme générique de bas niveau pour la gestion des événements
� Sémantique de construction et de destruction
� Mécanisme de stockage d’information
� Méthodes usuelles
� void dispose() : libérer les ressources d’un composant
� Display getDisplay() : récupère le Display associé au composant
� addListener(int, Listener) : mécanisme d’abonnement
� …
� Cette classe ne peut être étendue pour le développement
34SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
La classe Control
� La classe Control dérive de la classe Widget et chaque objet
Control encapsule un composant graphique natif : un peer
� Tous les composants SWT à l’exception de ScrollBar et
Menu sont des Control
� La classe Control fournit des méthodes pour contrôler
l’affichage et le comportement
� Taille, couleur, police, menu popup, …
� Abonnement aux écouteurs (listeners typés)
� De nombreuses méthodes … se référer à l’API
35SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comGalerie des composants : conteneurs
Shell
CompositeCoolBar
ToolBar
Combo
Spinner
Canvas
Browser
36SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Galerie des composants : conteneurs (suite)
Tree
Table
StyledText
CTabFolder
ExpandBar
Group
TabFolder
ScrolledComposite
37SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Galerie des composants : contrôle
Button (SWT.ARROW)
Button (SWT.PUSH) Button (SWT.CHECK)
Button (SWT.TOGGLE)
Button (SWT.RADIO)
LinkLabel
38SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comGalerie des composants : contrôle (suite)
Slider
Scale
Text (SWT.SINGLE)
Text (SWT.MULTI)
Sash
List
39SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Galerie des composants : les autres
Menu
Tray System
40SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : Shell
� Shell permet la création d’une fenêtre (équivalent à la JFrame de Swing)
� Fenêtre indépendante dont l’apparence peut varier en fonction du style donné lors de la construction
� Possibilité de créer des sous fenêtres associées une fenêtre parent
� Construction� Shell(Display) : construit un Shell (style défaut) associé à un Display
� Shell(Display, int) : avec un style défini
� Shell(Shell) : construit un Shell associé à un Shell parent
� Méthodes utiles� setVisible(boolean) : rend visible ou pas la fenêtre
� open() : appel un ensemble de fonctionnalités (visible, active, …)
41SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : Shell
� Les styles d’une fenêtre (constantes de la classe SWT)
� BORDER : ajoute un border
� CLOSE : ajoute un bouton de fermeture
� MIN : ajoute un bouton pour minimiser la fenêtre
� MAX : ajoute un bouton pour maximiser la fenêtre
� RESIZE : ajoute un border pour le redimensionnement
� TITLE : ajoute une barre de menu
� Paramètres pré-définis
� NO_TRIM : fenêtre sans possibilité de redimensionner, agrandir,minimiser, déplaçable, border, …
� DIALOG_TRIM : TITLE | CLOSE | BORDER
� SHELL_TRIM : CLOSE | TITLE | MIN | MAX | RESIZE
42SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
� Les fenêtres modales
� SYSTEM_MODAL : modale au système complet (peu répandu)
� APPLICATION_MODAL : création d’une fenêtre modale à l’application
� PRIMARY_MODAL : création d’une fenêtre modale
� MODE_LESS : non modale
Les conteneurs de SWT : Shell
NO_TRIM
DIALOG_TRIMSHELL_TRIM
43SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : Composite
� La classe Composite s’occupe de la gestion des conteneurs
� Elle peut contenir des composants Control et par conséquent
d’autres objets de type Composite
� Un objet Composite doit être rattaché directement à un objet
Shell, ou indirectement via d’autres conteneurs
� Les composants sont ajoutés au conteneur au moment de la
construction des composants (En Swing les composants sont
ajoutés par l’intermédiaire de la méthode add du conteneur)
44SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : Composite
� Un conteneur gère l’agencement des composants par un
agent de placement
� Différentes méthodes utiles
� Composite(Composite, int) : constructeur d’un Composite
� layout(boolean) : active ou pas l’agencement
� setLayout(Layout) : modifie l’agent de placement
� Control[] getChildren() : retourne le nombre de Control contenu
� setFocus() : affecte le focus au conteneur
La classe Shell étudiée précédemment est du
type Composite
45SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : Group
� Le conteneur Group est similaire à la classe Composite, il impose une délimitation et permet d’ajouter un titre
� En Swing, il s’agit d’un JPanel décoré d’un TitledBorder
� Différentes méthodes utiles
� setText(String p) : modifie le titre du Group
� String getText() : récupère le titre du Group
� Exemple : des composites décorésGroup temp = new Group(sShell, SWT.NONE);temp.setText("Action");temp.setLayout(new FillLayout(SWT. HORIZONTAL));Button myButton = new Button(temp, SWT. NONE);myButton.setText("i -> i + 1");temp = new Group(sShell, SWT. NONE);temp.setText("Résultat");temp.setLayout(new FillLayout(SWT. HORIZONTAL));Label myLabel = new Label(temp,SWT. CENTER);myLabel.setText("i = " + i); }
46SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : ToolBar
� ToolBar permet d’ajouter une barre d’outils en contenant un ensemble de composants prédéfinis (Button, Toggle, …)
� Une ToolBar peut être horizontale ou verticale
� Chaque élément d’une barre d’outil est défini par un ToolItem
� Apparence d’un ToolItem (constantes de la classe SWT)� CHECK : un bouton de sélection (Toggle)
� DROP_DOWN : un bouton avec un chevron
� PUSH : un bouton classique
� RADIO : un bouton de type radio (singleton sur la sélection)
� SEPARATOR : un séparateur
ToolBar toolBar = new ToolBar(shell, SWT.HORIZONTAL)Ou
ToolBar toolBar = new ToolBar(shell, SWT.VERTICAL)
47SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : ToolBar
� Différentes méthodes pour ToolItem
� setControl(Control) : modifie le contrôle quand l’item est un séparator
� setSelection(boolean) : sélectionne ou pas
� setEnabled(boolean) : active ou désactive
� setText(String) : modifie le texte
� setToolTipText(String) : modifie la bulle d’aide
� setWidth(int) : modifie la taille en pixel de l’élément
� Utilisation de la méthode setControl(Control)
� Possibilité d’ajouter des composants Control à la ToolBar
� Nécessite que le style du ToolItem soit SEPARATOR
48SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : ToolBar
� Exemple : une barre d’outils …
public class ToolBarExample {public ToolBarExample() {
Display display = new Display ();Shell shell = new Shell (display);ToolBar bar = new ToolBar (shell, SWT. HORIZONTAL);ToolItem item = new ToolItem (bar, SWT. PUSH);item.setText("Item 1");
Button myButton = new Button(bar,SWT. NONE);myButton.setText("Ici");item = new ToolItem(bar,SWT. SEPARATOR);myButton.pack();item.setWidth(myButton.getSize().x);item.setControl(myButton);
bar.pack ();shell.pack ();shell.open ();while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();}display.dispose ();
...}
Ajout d’un objet Control dans la barre de menu
ToolBarExample.java du projet IntroExamples
49SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les conteneurs de SWT : CoolBar
� La CoolBar fonctionne sur le même principe que la ToolBar à
la différence où les éléments sont flotants
� Pour interdire le déplacement d’éléments dans une CoolBar
utiliser la méthode setLocked(boolean)
� Les éléments contenus dans une CoolBar sont définis par des
CoolItem
Element déplaçableElement déplaçable
50SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes composants de contrôle : Button
� La classe Button représente un bouton cliquable
� A la différence de Swing où chaque type de bouton à une classe prédéfinie (JButton, JRadioButton, JCheckBox, …) le SWT se base sur les styles
� Différentes méthodes utiles� setText(String) : modifie le texte du bouton
� setSelection(boolean) : modifie la sélection
� Différentes apparences (constantes de la classe SWT)
� PUSH ou NONE : bouton par défaut
� CHECK : case à cocher
� RADIO : bouton radio
� TOGGLE : bouton de sélection
� ARROW : bouton avec flèche
51SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes composants de contrôle : Button
� Exemple : un ensemble de boutons
public class ButtonsExample {public ButtonsExample() {
Display display = new Display ();Shell shell = new Shell (display);shell.setText("Buttons Example");shell.setLayout(new FillLayout(SWT. VERTICAL));Button myButton = new Button(shell,SWT. PUSH);myButton.setText("Push Me");myButton = new Button(shell,SWT. CHECK);myButton.setText("Check Me");myButton = new Button(shell,SWT. RADIO);myButton.setText("Radio Me");myButton = new Button(shell,SWT. RADIO);myButton.setText("Radio Me");myButton = new Button(shell,SWT. TOGGLE);myButton.setText("Select Me");myButton = new Button(shell,SWT. ARROW);myButton.setText("Turn Me");
...}
Les boutons de type RADIOsont groupés s’ils appartiennent
au même Composite
ButtonsExample.java du projet IntroExamples
52SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes composants de contrôle : Label et Text
� La classe Label permet d’afficher un texte ou une image� setText(String) : modifie le texte
� setImage(Image) : modifie l’image
� La classe Text est une zone de texte contenant une ou plusieurs ligne (SINGLE ou MULTI)� setText(String) : modifie le texte
� setTextLimit(int) : définit la limite de la chaîne
� setEditable(boolean) : précise si la zone de texte est éditable
� Exemple : un ensemble de textespublic class LabelTextExample {
public LabelTextExample() {Display display = new Display ();Shell shell = new Shell (display);shell.setText("Buttons Example");shell.setLayout(new FillLayout(SWT.VERTICAL));Label myLabel = new Label(shell, SWT.BORDER);myLabel.setText("Message");Text myText = new Text(shell, SWT.BORDER | SWT.MULTI) ;myText.setText("Coucou");
...}
LabelTextExample.java du projet IntroExamples
53SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
L’art de placer les composants SWT
� Les agents de placement ou Layout Manager
FillLayout
RowLayout
FormLayout
GridLayout StackLayout
54SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement et les composants
� Les agents de placement permettent d’agencer les widgetscontenus dans un objet Composite
� Un agent de placement hérite de classe Layout
� Il peut s’agir de composants de type Control ou Composite
� L’agent de placement est associé à un objet Composite� setLayout(Layout) : modification d’un agent de placement
� Chaque widget peut influencer son comportement dans son conteneur par la méthode
� setLayoutData(Object) : objet spécifique suivant le type d’agent de placement
� Pour appliquer l’agencement et le re-dimensionnement des objets Control, utiliser la méthode pack()
55SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FillLayout
� Affiche horizontalement ou verticalement les composants les uns à la suite des autres
� VERTICAL ou HORIZONTAL constantes de la classe SWT
� Tous les composants sont redimensionnés de manière identique, ne conserve donc pas la taille des composants
� Dés que le conteneur est redimensionné les composants se distribuent l’espace
� Exemple : boutons alignés verticalementsShell.setLayout( new FillLayout(SWT. VERTICAL) );Button myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 1");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 2");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 3");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 4");
FillLayout.java du projetLayoutExamples
56SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : RowLayout
� Affiche horizontalement ou verticalement les composants les
uns à la suite des autres (si possible)
� VERTICAL ou HORIZONTAL constantes de la classe SWT
� Possibilité de conserver la taille des composants
� Si pas assez de place débordement sur une nouvelle ligne ou
une colonne
� Peut être comparé à l’agent de placement FlowLayout de
Swing (mais en plus expressif)
� Possibilité de contraindre chaque composant par un objet de
type RowData
� RowData(int width, int height) : largeur et hauteur
57SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : RowLayout
� RowLayout peut être paramétré après sa construction
� boolean justify : précise si les composants doivent être justifiés
� int marginBottom, marginTop : marge du bas et du haut
� int marginLeft, marginRight : marge à gauche et à droite
� boolean pack : si true les composants gardent leur taille préférée
� int spacing : espace entre les contrôles
� int type : orientation (SWT.VERTICAL ou SWT.HORIZONTAL)
� boolean wrap : si true retour à la ligne quand plus de place
58SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : RowLayout
RowLayout myLayout = new RowLayout(SWT.HORIZONTAL);myLayout.wrap = true;sShell.setLayout(myLayout);Button myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 1");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 2");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 3");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 4");myButton.setLayoutData( new RowData(100,100) );
� Exemple : un ensemble de boutons
Le dernier bouton est agrandi
Différents résultats en fonction de la taille de la fenêtre
RowLayoutExample.java du projet LayoutExamples
59SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : GridLayout
� L’agent de placement GridLayout est un des plus expressif et
pourrait être suffisant
� Il contrôle une grille avec la possibilité de fusionner des
cellules et de contraindre ou pas la largeur des cellules
� Comparable au GridLayout de Swing en plus expressif
� Construction d’un GridLayout
� GridLayout(int nc, boolean ew) : construit un GridLayout avec nc
nombre de colonnes. Si ew = true les colonnes ont la même taille
� GridLayout() : construit un GridLayout avec une colonne et les
colonnes n’auront pas la même taille
60SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : GridLayout
� GridLayout peut être paramétré après sa construction
� int horizontalSpacing : espace horizontal entre les cellules
� int verticalSpacing : espace vertical entre les cellules
� boolean makeColumnsEqualWidth : true = force toutes les colonnes à
avoir la même taille
� int marginHeight, marginWidth : marge en largeur et en hauteur
� int numColumns : nombre de colonne
� Possibilité de contraindre chaque composant par un objet de
type GridData
� GridData(int style) : construit un GridData avec un style spécifié
61SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : GridLayout
� GridData peut être paramétré après sa construction
� int horizontalSpan : le nombre de colonne occupé
� int verticalSpan : le nombre de ligne occupé
� int horizontalAlignment : précise le type d’alignement GridData.FILL,.BEGINNING, .CENTER et .END
� boolean grabExcessHorizontalSpace : si TRUE force la cellule à remplir l’espace disponible
� …
� Les différentes constantes utilisables
� FILL_BOTH : rempli l’espace disponible horizontal et vertical
� FILL_HORIZONTAL : rempli l’espace disponible horizontal
� FILL_VERTICAL : rempli l’espace disponible vertical
� …
FILL, BEGINNING, CENTER et END ne sont pas utilisables pour
construire un GridData
62SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : GridLayout
� Exemple : un ensemble de boutonsGridLayout myLayout = new GridLayout(3, false);sShell.setLayout(myLayout);Button myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 1");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 2");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 3");myButton = new Button(sShell, SWT. NONE);myButton.setText("Bouton 4");GridData myData = new GridData(GridData.FILL_BOTH);myData.horizontalSpan = 3;myButton.setLayoutData(myData);
Trois cellules en haut
Trois cellules fusionnées
GridLayoutExample.java du projet LayoutExamples
63SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� L’agent de placement FormLayout organise les Control en
exploitant des contraintes de placement
� Comparable au GridBagLayout de Swing
� Possibilité de contraindre chaque composant par un objet de
type FormData
� Utilisation d’un objet additionnel FormAttachment lié au
FormData pour contrôler la taille et le placement
� Attributs d’un FormData
� int height, width : hauteur et largeur pour le Control
� FormAttachment bottom, left, right, top : la contrainte pour le bas, la
gauche, la droite et le haut du Control
64SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� FormAttachment définit comment les composants sont positionnés entre eux
� Cet objet permet de définir l’alignement et la taille d’un Control
� Un FormAttachment peut être associé à un Control pour définir ainsi des contraintes entre objets Control
� Représentation mathématique de l’objet FormAttachmentsous la forme d’une équation de type : y = a x + b
� y = coordonnées après attachement
� x = coordonnées avant attachement
� a = pourcentage de l’objet attaché ( a = numérateur / dénominateur)
� b = offset
65SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Attributs d’un FormAttachment
� int alignment : côté du Control avec lequel le FormAttachment sera attaché SWT.TOP, .CENTER, .BOTTOM, .LEFT, .RIGHT
� Control control : l’objet Control associé au FormAttachment
� int denominateur : dénominateur de a (défaut : 100)
� int numerator : numérateur de a
� int offset : décalage
� Construction d’un FormAttachment
� FormAttachment(Control p, int offset)
� FormAttachment(int numerator, int offset)
� FormAttachment(int numerator, int denominateur, int offset)
� …
66SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Exemple (EP 1) : FormLayout sans FormAttachmentFormLayout formLayout = new FormLayout();shell.setLayout(formLayout);FormData formData = new FormData();formData.height = 120;formData.width = 120;
Button button = new Button(shell, SWT. PUSH);button.setLayoutData(formData);button.setText("Button 1");
Le bouton conserve sa taille préférée lors de l’agrandissement de
son container
FormLayoutExample1.java du projet LayoutExamples
67SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Exemple (EP 2) : FormLayout avec FormAttachmentFormLayout formLayout = new FormLayout();shell.setLayout(formLayout);FormData formData = new FormData();formData.height = 120;formData.width = 120;formData.left = new FormAttachment(0,20);
formData.right = new FormAttachment(100,-20);
formData.top = new FormAttachment(0,20);
formData.bottom = new FormAttachment(100,-20);
Button button = new Button(shell, SWT. PUSH);button.setLayoutData(formData);button.setText("Button 1");
Fixé à 20 pixels à gauche
Fixé à 20 pixels à droite
Fixé à 20 pixels en haut
Fixé à 20 pixels en bas
Le bouton est collé au partie droite et basse
FormLayoutExample2.java du projet LayoutExamples
68SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Exemple (EP 2) bis : FormLayout avec FormAttachmentCôté droit
y = (100 / 100) x - 20
Côté gauche
y = (0 / 100) x + 20
A chaque re-dimensionnement du conteneur la position du côté
droit du bouton varie linéairement A chaque re-dimensionnement du conteneur la position du côté
gauche du bouton ne change pas
x (coordonnées avant attachement)
x (coordonnées après attachement)
69SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Exemple (EP 2) bis : FormLayout avec FormAttachmentNumérateur = 0, offset > 0
Numérateur = 100, offset < 0
Numérateur = 0, offset > 0
Numérateur = 100, offset > 0
Valeurs pour les cas généraux du moment que les FormAttachment
ne sont pas liés à un Control
70SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : FormLayout
� Exemple (EP 3) : FormLayout avec FormAttachment et Control associé FormLayout formLayout = new FormLayout();
shell.setLayout(formLayout);
Button button1 = new Button(shell, SWT. PUSH);button1.setText("Button 1");
Button button2 = new Button(shell, SWT. PUSH);button2.setText("Button 2");
FormData formData = new FormData();formData.left = new FormAttachment(0,20);formData.right = new FormAttachment(100,-20);formData.top = new FormAttachment(0,20);formData.bottom = new FormAttachment(button2,0,SWT. TOP);button1.setLayoutData(formData);
formData = new FormData();formData.left = new FormAttachment(0,20);formData.right = new FormAttachment(100,-20);formData.bottom = new FormAttachment(100,-20);formData.top = new FormAttachment(1,2,0);button2.setLayoutData(formData);
Relier le bas de bouton1 avec le haut du bouton2FormLayoutExample3.java du
projet LayoutExamples
71SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : StackLayout
� L’agent de placement StackLayout permet d’empiler des Control et de choisir celui qui sera visible
� Similaire au CardLayout de Swing
� Ne fait pas partie du package org.eclipse.swt.layout
� StackLayout peut être paramétré après sa construction� int marginHeight : marge en hauteur
� int marginWidth : marge en largeur
� Control topControl : objet Control à afficher
� Si l’objet topControl est null aucun objet Control ne sera affiché
� Pour changer d’objet Control à afficher� Modifier l’objet contenu dans topControl du StackLayout
� Appeler layout() du Composite
72SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes agents de placement : StackLayout
� Exemple : StackLayout et deux boutonsfinal Shell shell = new Shell (display);final StackLayout stackLayout = new StackLayout();shell.setLayout(stackLayout);
Button button1 = new Button(shell, SWT. PUSH);button1.setText("Button 1");
final Button button2 = new Button(shell, SWT. PUSH);button2.setText("Button 2");
button1.addSelectionListener(new SelectionAdapter() {public void widgetSelected(SelectionEvent arg0) {
stackLayout.topControl = button2;shell.redraw();
}});
stackLayout.topControl = button1;
A la suite de l’action sur button1, button2devient l’objet Control
courant dans le StackLayout
FormLayoutExample3.java du projet
LayoutExamples
73SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les agents de placement : aucun …
� Ne pas utiliser d’agent de placement vous impose pour
chaque composant de :
� les positionner dans leur parent
� définir la taille
� L’absence d’agent de placement ne permet pas de produire
des interfaces qui s’adaptent au système
� Pour préciser que vous ne voulez pas d’agent de placement
donner une valeur null à la méthode setLayout(…)
� Dans quels cas ne pas utiliser d’agent de placement
� Construction d’un GUI-Builder
74SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les agents de placement : aucun …
� Exemple : sans agent de placement avec 2 boutonsShell shell = new Shell (display);shell.setLayout(null);
Button button = new Button(shell, SWT. PUSH);button.setText("Button 1");button.setBounds(0, 0, 125, 125);
button = new Button(shell, SWT. FLAT);button.setText("Button 2");button.setBounds(0, 125, 125, 125);
button = new Button(shell, SWT. FLAT);button.setText("Button 3");button.setBounds(0, 250, 125, 125);
Le LayoutManager du Shell est null
Modification de la position et de la taille
pour chaque composant
StackLayoutExample.java du projet LayoutExamples
75SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Conception et programmation
� Affichage des informations vers l’utilisateur
� Instanciation des composants de la BAO SWT
� Mise en place des composants visibles grâce à des conteneurs et agents de placement
� Mais l’interface ne peut pas réagir aux actions de l’utilisateur
� Clic sur le bouton
� Terminaison de l’application
� Réaction aux actions de l’utilisateur
� En SWT, toute interaction est encapsulée dans un événement
� Le traitement des interactions revient à récupérer et interpréter les événements
� SWT utilise le principe de l’abonnement
76SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements SWT
� Chaque composant de l’interface graphique peut émettre des événements� C’est une source (Widget)
� Des objets peuvent recevoir ces événements� Ce sont des écouteurs (les listeners)
� La liaison entre source et écouteur se fait par abonnement� On associe à une source un ou plusieurs écouteurs et réciproquement
� SWT fournit deux types de listeners� Les listeners non typés (Listener)� Les listeners typés (EventListener)
� Les événements sont définis par une classe Java qui dépend du type de listener� Event pour les listeners non typés� TypedEvent pour les listeners typés
77SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comIntérêt du traitement par abonnement
� Exemple d’un compteur qui incrémente et décrémente� Deux boutons
� « OUI » incrémente une variable
� « NON » décrémente la même variable
� Un son est émis à chaque pression sur un des boutons
� Un bouton est associé deux fois à un même événement avec deux actions différentes
+1 -1Beep !
SelectionEventSelectionEvent SelectionEvent
78SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comIntérêt du traitement par abonnement
� En quoi consiste l’abonnement ?
� Enregistrer (abonner) auprès de l’objet source un écouteur
� Exemple :
� Qu’est-ce qu’un écouteur ?
� Une classe (même anonyme) qui implémente une interface (au sens
Java du terme)
monBouton.addListener(monListener);
Selon le type d’écouteur, la méthode d’abonnement et la classe de l’écouteur varient
79SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners non typés
� Les listeners non typés sont représentés par l’interface Listener contenant une seule méthode
� void handleEvent(Event event) : méthode de traitement d’un événement
� L’abonnement à cet écouteur non typé est effectué par la méthode (présente dans la classe Widget)� void addListener(int eventType, Listener listener) : méthode réalisant
l’abonnement entre une source (Widget) et un objet de type Listenerpour le type d’événement défini par eventType
button.addListener(SWT.SELECTION, new Listener() {public void handleEvent(Event e) {
switch(e.type) {case SWT.SELECTION :
System.out.println("Button Pressed");break;
}}
}
button est une source
Abonnement de button avec un listener pour écouter un événement SELECTION
Traitement de l’événement
80SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners non typés
� Le type d’événement à considérer au cours de l’abonnement est défini par des constantes de type int stockées dans SWT
� Activate : fenêtre active
� Close : widget terminé
� Collapse : un nœud d’arbre réduit
� Deactivate : fenêtre non active
� Dispose : composant détruit
� Expand : un nœud d’arbre éclaté
� FocusIn : widget gagne le focus
� FocusOut : widget perd le focus
� KeyDown : presse une touche clavier
� KeyUp : relacher une touche clavier
� MouseEnter : souris entre dans un widget
� MouseExit : souris sort du widget
� MouseHover : souris au dessus du widget
� MouseMove : souris se déplace dans widget
� MouseUp : bouton souris relaché
� MouseDown : bouton souris pressé
� MouseDoubleClick : pour le double click
� Move : déplacement d’un widget
� Paint : le widget est dessiné
� Resize : widget rediemensionné
� Selection : widget sélectionné
� Show : widget affiché
� …
81SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners non typés
� La classe Event permet de définir le contenu de l’événement
� Elle contient des attributs qui caractérisent l’événement
� Certains attributs sont dépendants du type d’événement
considéré
� Par exemple pour l’événement de type MouseDoubleClick
� int button : modélise le bouton de la souris : 1 pour le bouton de
gauche, 2 pour le second et 3 pour le troisième
� int type : le type de l’événement considéré
� int time : la date à laquelle l’événement a été provoquée
� int x et y : position de la souris
� Widget item : la source de l’événement
82SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners non typés
� Exemple : un bouton et des réactions
...myButton.addListener(SWT. MouseDoubleClick, new Listener() {
public void handleEvent( Event event ) {System. out.println("Type de l'événement : " + event.type );((Button) event.widget ).setText("DoubleClick");System. out.println("Date de déclenchement : " + event.time );System. out.println("Position x et y : " + event.x + " / " + event.y );System. out.println("Quel bouton ? : " + event.button );
}});...
InfoEventExample.java du projet EventExamples
83SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners typés
� Les listeners typés sont représentés par un ensemble d’interface stockés dans le package org.eclipse.swt.events
� Les listeners typés fournissent en quelque sort une encapsulation du type d’événement
� Pour chaque famille d’événement un listener est proposé
� MouseListener : écouteur adapté pour les événements de clicks de la souris
� Chaque listener propose un ensemble de méthodes associé àun type précis d’événement
� mouseDoubleClick(MouseEvent e) : pour le double click
� mouseDown(MousEvent e) : quand le bouton est pressé
� mouseUp(MouseEvent e) : quand le bouton est levé
84SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners typés
85SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Traitement des événements : les listeners typés
86SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Programmation du traitement
� Créer une source
� Instancier un composant (e.g. un Button) pour l’affichage, c’estautomatiquement une source d’événements
� Ne pas oublier de garder une référence disponible sur ce composant
� Créer un écouteur
� Implémenter dans une classe une des interfaces du package events(e.g. un SelectionListener) selon le type d’événement écouté
� Coder les effets de bord attendus dans une des méthodes de cette classe (e.g. public void widgetSelected(SelectionEvent))
� Instancier un objet de cette classe
� Abonner l’écouteur à la source
� Abonner l’instance de la source à l’instance de l’écouteur
87SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
� Créer le composant Button
� Créer l’écouteur des SelectionEvent� Implémenter l’interface SelectionListener
� Insérer les effets de bord dans la méthode
� public void widgetSelected(SelectionEvent evt)
� Abonner l’écouteur à l’objet émetteur d’événements
� Utiliser la méthode d’abonnement proposée par le composant source
� addSelectionListener(SelectionListener al)
Programmation du traitement : exemple
SelectionEvent
ControlEvent
KeyEvent
MouseEvent
…
SelectionListener
88SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comProgrammation du traitement : exemple
� Exemple : un bouton abonné à un SelectionListenerpublic class CompteurWithEvent {
private int i = 0;private Label myLabel;public CompteurWithEvent() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");myShell.setLayout(new FillLayout(SWT.VERTICAL));Button myButton = new Button(myShell,SWT.NONE);myButton.addSelectionListener(new SelectionListener () {
public void widgetDefaultSelected(SelectionEvent e) {}
public void widgetSelected(SelectionEvent e) {i++;myLabel.setText("i = " + i);
}});myButton.setText("i->i+1");myLabel = new Label(myShell, SWT.CENTER);myLabel.setText("i = 0");...
}}
Méthode implémentée à vide car pas utile
Nécessite que myLabel
soit vu comme
attribut de la classe
CompteurWithEvent.javadu projet EventExamples
89SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comProgrammation du traitement : exemple
� Exemple : une fenêtre qui ne se ferme pas …public class CloseShellExample {
public CloseShellExample() {Display display = new Display();final Shell myShell = new Shell(display);shell.setLayout(new FillLayout());shell.setText("CloseShellExample");shell.addShellListener(new ShellAdapter() {
public void shellClosed(ShellEvent event) {event.doit = false;
}});
Button myButton = new Button(shell, SWT. FLAT);myButton.setText("Une fenêtre qui ne se ferme pas c omme d'habitude");myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent arg0) {shell.dispose();
}});...
}}
Quand une fenêtre est fermée, elle est
disposée.
Pour empêcher le dispose
Il faut cliquer sur le bouton pour fermer la
fenêtre
CloseShellExample.java du projet EventExamples
90SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comProgrammation du traitement : exemple
� Certaines interfaces écouteur (Listener) ont une équivalence
adaptateur (Adapter)
� Une classe adaptateur est une implémentation à vide d’un
écouteur
� De façon générale s’il y a plus d’une méthode à implémenter
un adapter est obligatoirement fourni
� En utilisant un adaptateur de l’héritage est effectuée et plus
précisément de la re-définition de méthodes
� Inversement une interface nécessite une implémentation de
l’ensemble des méthodes
91SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comProgrammation du traitement : exemple
� Exemple : un bouton abonné à un SelectionListener par l’intermédiaire d’un adapter
public class CompteurWithEvent2 {private int i = 0;private Label myLabel;public CompteurWithEvent2() {
Display display = new Display();Shell myShell = new Shell(display);myShell.setText("Compteur");myShell.setLayout(new FillLayout(SWT.VERTICAL));Button myButton = new Button(myShell,SWT.NONE);myButton.addSelectionListener(new SelectionAdapter( ) {
public void widgetSelected(SelectionEvent e) {i++;myLabel.setText("i = " + i);
}}myButton.setText("i->i+1");myLabel = new Label(myShell, SWT.CENTER);myLabel.setText("i = 0");...
}}
Héritage de la classe SelectionAdapter
Nécessite que myLabel
soit vu comme
attribut de la classe
Faites attention lors de la re-définition des méthodes à ne pas vous tromper dans
leur signatureCompteurWithEvent2.java du projet EventExamples
92SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comProgrammation du traitement : les recettes
� Pour abonner un composant à un écouteur trois recettes sont envisageables
� Abonnement par un écouteur externe
� Une classe externe s’occupe spécifiquement du fonctionnement de l’écouteur
� Abonnement par un écouteur interne
� La classe où se trouve les sources (la partie graphique) sert également d’écouteur
� Abonnement par un écouteur locale
� Pour chaque abonnement avec une source, utilisation d’une classe anonyme« inner class »
� Exemple : abonnement d’un bouton à MouseListener (cet écouteur possède trois méthodes)
93SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comAbonnement par un écouteur externe
� La définition de l’écouteur se fait en dehors de la classe
Exemple
� Il faut implémenter chacune des méthodes même s’il n’y a
rien à mettre dedans
� Difficulté d’accéder aux attributs de la classe Exemple
public class Exemple {...public Exemple() {
...myBut.addMouseListener(new EcouteurInterface());
}}
public class EcouteurInterface implements MouseListener {
public void mouseDoubleClick(MouseEvent e) {...}
public void mouseDown(MouseEvent e) {}
public void mouseUp(MouseEvent e) {}
}
Cet écouteur est utilisé par la classe
Exemple
94SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Abonnement par un écouteur externe : adapter
� La définition de l’écouteur se fait en dehors de la classe
Exemple
� Il faut redéfinir chacune des méthodes même s’il n’y a rien
à mettre dedans
� Difficulté d’accéder aux attributs de la classe Exemplepublic class EcouteurAdapter extends MouseAdapter {
public void mouseDoubleClick(MouseEvent e) {...}
public void mouseUp(MouseEvent e) {...}
}public class Exemple {
...public Exemple() {
...myBut.addMouseListener(new EcouteurAdapter());
}}
Cet écouteur est utilisé par la classe
Exemple
Redéfinition uniquement des méthodes nécessaires
95SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comAbonnement par un écouteur interne
public class Exemple implements MouseListener {...public Exemple() {
...myBut.addMouseListener(this);
}
public void mouseDoubleClick(MouseEvent e) {this.myBut...
}
public void mouseDown(MouseEvent e) {}
public void mouseUp(MouseEvent e) {}
}
� La définition de l’écouteur se fait dans la classe Exemple par implémentation
� Il faut implémenter chacune des méthodes même s’il n’y a rien à mettre dedans
� Possibilité d’accéder facilement aux attributs de la classe Exemple
Accès aux attributs de la
classe
Implémentation àvide
96SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Abonnement par un écouteur locale : interface
� La définition de l’écouteur se fait dans une « inner classe »par implémentation et localement à la classe Exemple
� Il faut implémenter toutes les méthodes même s’il n’y a rien dedans
� Possibilité d’accéder facilement aux attributs de la classe Exemple public class Exemple {
...public Exemple() {
...myBut.addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent e) {Exemple.this.myBut...
}
public void mouseDown(MouseEvent e) {}
public void mouseUp(MouseEvent e) {}
});}
}
Implémentation à vide
Accès aux attributs de la classe
97SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Abonnement par un écouteur locale : adapter
public class Exemple {...public Exemple() {
...myBut.addMouseListener(new MouseAdapter() {
public void mouseDoubleClick(MouseEvent e) {Exemple.this.myBut...
}});
}}
� La définition de l’écouteur se fait dans une « inner classe »par dérivation et localement à la classe Exemple
� Il faut redéfinir les méthodes dont on a besoin
� Possibilité d’accéder facilement aux attributs de la classe Exemple
� Cette solution et la précédente sont à utiliser si le traitement de l’écouteur est utilisé par une seule source
Ne vous trompez pas dans la signature des
méthodes sinon risque de définition
de nouvelles méthodes
98SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context
� Possibilité de dessiner en utilisant la classe GC (GraphicalContext) sur des Control, Image et Device
� GC fournit un ensemble de méthodes pour dessiner des formes, des textes et des images
� Principe
� Récupération ou création du GC
� Traitement du dessin
� Si le GC a été créé, libérer la ressource
� Récupération du GC avec l’écouteur PaintListenermyComponent.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {event.gc.setBackground(...);
}});
Le GC n’est pas créé mais récupéré du Control
myComponent
99SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context
� La construction d’un GC se fait par l’intermédiaire d’un objet Drawable (Control, Device et Image)
� L’objet Canvas est spécialement conçu pour le dessin
� A la différence des autres objets Control, Canvas dessine un rectangle plein d’une couleur par défaut
� Possibilité de paramétrer le comportement du Canvas
� SWT.NO_BACKGROUND : pas de couleur pour le fond
� SWT.NO_REDRAW_SIZE : pas de dessin pour le re-dimensionnement
� …
GC myGC = new GC(myControlComponent);myGC.drawText(...);myGC.drawLine(...);...myGC.dispose();
N’oubliez pas, si vous créez vous devez disposez !!!
100SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les couleurs
� La couleur est définie par la classe Color� Color(Device d, RGB rgb)
� Un objet RGB défini un triplet de trois composantes
� RGB(int red, int green, int blue)
� Possibilité de récupérer des couleurs définies par SWT par l’intermédiaire de la classe Display� getSystemColor(int color) : constantes définies dans SWT
� Des méthodes pour modifier la couleur du GC� setBackground(Color color) : Modification de la couleur de fond pour
les opérations de remplissage et pour le fond du texte
� setForeground(Color color) : modification de la couleur de dessin et pour la couleur d’écriture du texte
� setAlpha(int alpha) : modification de l’opacité (alpha) de la couleur (0 transparent, 255 opaque)
101SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les couleurs
� Exemple : création, récupération, utilisation et libération de couleurs
...myCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {Color myColor = new Color(Display.getDefault(), new R GB(200,212,123));event.gc.setBackground(myColor);event.gc.setAlpha(100);event.gc.fillRectangle(0,0,200,200);event.gc.setForeground(Display.getSystemColor(SWT.C OLOR_BLUE));event.gc.drawText("Message à afficher", 20, 20, true );myColor.dispose();
}}...
Le texte sera affichésur fond transparent
L’objet Color myColordoit être disposé
Récupéré donc ne pas disposer
ColorGraphicContextExample.javadu projet GraphicExamples
102SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les formes
� Dessine de points, lignes, poly-lignes, rectangles, polygones, ellipses, arcs, …
� drawXXX(…) : dessine une forme XXX
� Dessine des formes pleines comme des rectangles, ellipses, arcs, …
� fillXXX(…) : dessine une forme pleine XXX
� Modification des caractéristiques d’une ligne
� setLineStyle(int style) : modification du style de la ligne
� setLineWidth(int style) : modification de la taille de la ligne
� Modification de la zone utilisée pour l’affichage (clipping)
� setClipping(Rectangle p) : définition d’une zone par un Rectangle(également un Path ou une Region)
103SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les formes
� Exemple : dessiner des formes...myCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {event.gc.setForeground(Display. getDefault().getSystemColor(SWT. COLOR_BLUE));event.gc.setBackground(Display. getDefault().getSystemColor(SWT. COLOR_CYAN));event.gc.drawRectangle(0, 0, 150, 100);
event.gc.setLineStyle(SWT. LINE_DASHDOT);event.gc.setLineWidth(20);event.gc.drawOval(10, 10, 160, 110);
event.gc.setAlpha(150);event.gc.fillRectangle(20, 20, 250, 150);
}});...
Modification de l’aspect de transparence
ShapeGraphicContextExample.javadu projet GraphicExamples
104SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� Graphical Context offre la possibilité de dessiner du texte
� Différentes méthodes
� drawString(String p, int x, int y) : écrit le texte p à la position x et y
� drawString(String p, int, int y, boolean transp) : idem avec la possibilité de forcer la transparence du fond du texte
� drawText(String t, int x, int y) : idem avec la gestion de la tabulation \t, du retour à la ligne \n et d’un caractère mnemonic &
� drawText(String t, int x, int y, int flags) : idem au précédent avec gestion des caractères
� Gestion des caractères
� SWT.DRAW_DELIMITER : gère le retour à la ligne \n
� SWT.DRAW_TAB : gère la tabulation \t
� SWT.DRAW_MNEMONIC : gère le caractère mnemonic &
� SWT.DRAW_TRANSPARENT : fond transparent
105SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� Exemple : écrire du texte...final String maChaine = "Voici un texte \n utilisé pa r deux \t\t méthodes";myCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {event.gc.setForeground(Display. getDefault().getSystemColor(SWT. COLOR_BLUE));event.gc.drawString(maChaine, 0, 20);event.gc.drawText(maChaine, 0, 40, SWT. DRAW_MNEMONIC | SWT. DRAW_TAB |SWT.DRAW_DELIMITER) ;
}});...
Tabulation non prise en compte pour le drawString
TextGraphicContextExample.javadu projet GraphicExamples
106SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� Des méthodes pour retourner et modifier une fonte
� setFont(Font myFont) : modifie la fonte courante du GC
� Font getFont() : retourne la fonte courante du GC
� Un objet Font peut être construit à partir
� public Font(Device device, String name, int height, int style) : construit une fonte à partir d’une police name, d’une hauteur heightet d’un style style
� public Font(Device device, FontData fd) : construit une fonte à partir d’un Device et d’un FontData (voir ci-après)
� La création d’un objet Font implique la création d’un objet natif, donc si vous en créez un vous devrez le disposer
� Il existe une fonte par défaut utilisée par le GC si aucune fonte n’est explicité Display.getSystemFont()
107SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� Un objet FontData peut être vu comme une structure de
données des caractéristiques d’un objet Font
� FontData(String pvaleur, int height, int sty) : police pvaleur, une hauteur height et un style sty
� Un objet FontData est un objet manipulant une ressource du
système et peut être disposé (automatiquement disposé si
construit à partir d’un objet Font)
� Différentes méthodes :
� int getHeight() : retourne la hauteur de la police de caractères
� setHeight(int height) : modifie la hauteur
� String getName() : retourne le nom de la police
� setName(String name) : modifie le nom de la police
108SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
bonjour
� Les données de FontData ne permettent pas de connaître les différentes hauteur d’une police au cours du dessin
� Nécessite l’utilisation du FontMetrics qui ne peut être construit, mais est accessible via le GC� FontMetrics getFontMetrics() : extraction des hauteurs d’une fonte
� Les différentes hauteurs d’une fonte� int getAscent() : hauteur du corps
� int getDescent() : hauteur du pied
� int getLeading() : hauteur de la tête
� int getHeight() : hauteur de la fonte
Leading
Ascent
Descent
Height
109SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� En complément à l’objet FontMetrics, le Graphical Contextfournit des méthodes pour déterminer l’occupation pour une chaîne de texte
� Différentes méthodes
� Point stringExtent(String value) : retourne la largeur et la hauteur occupées par la chaîne de caractères définie par value
� Point textExtent(String value) : idem en tenant compte des caractères spécifiques \t, \n et &
� Point textExtent(String value, int flags) : idem en configurant les caractères spécifiques à prendre en compte
Ne confondez pas la hauteur d’une fonte et la hauteur d’un texte dessiné. Il s’agit de deux valeurs différentes. Pour la seconde, la valeur
dépend de la police, du style, …
110SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les textes
� Exemple : respecter la dimension d’un texte...final String maChaine = "Voici un texte \n utilisé pa r deux \t\t méthodes";myCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {event.gc.setForeground(Display. getDefault().getSystemColor(SWT. COLOR_BLUE));event.gc.drawString(maChaine, 0, 20);event.gc.drawText(maChaine, 0, 40, SWT. DRAW_MNEMONIC | SWT. DRAW_TAB |SWT.DRAW_DELIMITER) ;
Point maChainePoint = event.gc.textExtent(maChaine);event.gc.setForeground(Display. getDefault().getSystemColor(SWT. COLOR_BLACK));event.gc.drawRectangle(0, 40, maChainePoint.x, maChain ePoint.y);
}});...
TextSizeGraphicContextExample.javadu projet GraphicExamples
111SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Possibilité de charger des images à partir d’un fichier sur le disque (GIF, PNG, JPEG, TIFF, ICO, BMP et RLE)
� Possibilité de créer une image pour dessiner dessus
� Une image est encapsulée par la classe Image. Si vous créez un objet Image vous devrez disposer l’objet
� Différents constructeurs� Image(Device device, String filename) : construit une Image à partir
d’un fichier (chemin absolu)
� Image(Device device, InputStream stream) : à partir d’un flux
� Image(Device device, int width, int height) : vide avec une taille
� Image(Device device, Image source, int flat) : à partir d’un autre objet Image
� Image(Device device, ImageData data) : à partir d’un ImageData
112SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Exemple : création d’un objet Image à partir d’un fichier...Image image1 = new Image(Display. getDefault(), "D:/Documents
Mickey/Java/GraphicsExamples/example.jpg");Image image2 = null;try {
image2 = new Image(Display. getDefault(), new FileInputStream("D:/Documents Mickey/Java/GraphicsExamples/example.jpg"));
} catch(FileNotFoundException e) {e.printStackTrace();
}Image image3 = new Image(Display. getDefault(),
CreateImageExample.class.getResourceAsStream("/exam ple.jpg"));
new Label(shell, SWT. NONE).setImage(image1);new Label(shell, SWT. NONE).setImage(image2);new Label(shell, SWT. NONE).setImage(image3);...
Images ajoutées directement dans un Label, on verra dans la suite comment dessiner une image
dans le GC
CreateImageExample.java du projet GraphicExamples
113SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Exemple : copie d’un objet Image...final Image image = new Image(Display. getDefault(),
CreateImageExample.class.getResourceAsStream("/exam ple.jpg"));Image copyImage = new Image(Display. getDefault(), image, SWT.IMAGE_COPY);Image disableImage = new Image(Display. getDefault(), image, SWT.IMAGE_DISABLE);Image grayImage = new Image(Display. getDefault(), image, SWT.IMAGE_GRAY);
new Label(shell, SWT. NONE).setImage(copyImage);new Label(shell, SWT. NONE).setImage(disableImage);new Label(shell, SWT. NONE).setImage(grayImage);...
Flag qui indique comment effectué la copie (3 valeurs
disponibles)
CopyImageExample.java du projet GraphicExamples
114SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Dessiner un objet Image dans le Graphical Context est obtenu par deux méthodes� drawImage(Image image, int x, int y) : dessine une image à la
position x et y
� drawImage(Image image, int sX, int sY, int sWidth, int sHeight, intdX, int dY, int dWidth, int dHeight) : dessine une partie d’image définie par sX, sY, sWidth, sHeight à la position dX et dY avec une taille dWidth et dHeight
� Dessiner avec un agrandissement …...myCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {Image myImage = new Image(Display. getDefault(),200,200);GC gc = new GC(myImage);gc.drawString("Bonjour tout le monde", 0, 0, true);event.gc.drawImage(myImage, 0, 0,200,200,0,0,500,500) ;event.gc.drawString("Bonjour tout le monde", 0, 50, tr ue);gc.dispose();myImage.dispose();
}});...
Dessine tout d’abord sur l’image puis colle l’image dans le GC du
Canvas
ScaleTextExample.java du projetGraphicExamples
115SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
� Les données d’une image sont stockées dans un ImageData� byte[] data : les pixels d’une image
� int alpha : la transparence
� byte[] alphaData : l’alpha pour chaque pixel
� int depth : le poids d’un pixel
� int height, width : les dimensions d’une image
� int type (SWT.IMAGE_UNDEFINED, SWT.IMAGE_BMP, …) : le format
� …
� Les données sont indépendantes du Device (peut être l’écran ou l’imprimante)
� Constructeurs d’un ImageData� ImageData(String filename) : construit à partir d’un nom de fichier
� ImageData(InputStream filename) : construit à partir d’un stream
� ImageData(int width, int height, int depth, PaletteData p) : à partir d’une taille, profondeur et un palette
Dessiner avec Graphical Context : les images
116SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Différentes méthodes pour manipuler ImageData� int getPixel(int x, int y) : retourne la valeur du pixel à x et y
� void setPixel(int x, int y, int pixel) : modifie la valeur du pixel x et y
� int getAlpha(int x, int y) : retourne l’alpha du pixel x et y
� setAlpha(int x, int y, int alpha) : modifie l’alpha du pixel x et y
� ImageData scaledTo(int w, int h) : retourne une nouvelle image de taille différente (grossie ou réduite)
� …
� Principe pour afficher un ImageData modifié
� Modifier un ImageData (setPixel, setAlpha, …)
� Créer un objet Image associé à l’ImageData
� Pour chaque modification de l’ImageData, créer obligatoirement un objet Image pour afficher
Si vous créez un objet Image,
n’oubliez pas de le disposer si vous ne
l’utilisez plus
117SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : les images
� Exemple : un effet de transparence...Display display = new Display();Shell shell = new Shell(display);shell.setLayout(new FillLayout());shell.setText("ImagaDataAlphaColorExample");ImageData data = new ImageData("example.jpg");for (int i = 0; i < data.width; i++) {
for (int j = 0; j < data.height; j++) {data.setPixel(i, j, (data.getPixel(i, j) + 110) % 255);data.setAlpha(i, j, (data.height - j) % 254);
}}image = new Image(display, data);new Label(shell, SWT. NONE).setImage(image);...
L’ImageData est modifié, obligation de créer un objet Imagepour afficher les modifications
ImageDataAlphaColorExample.javadu projet GraphicExamples
118SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : Transform
� Possibilité d’appliquer des matrices de transformations sur
un Graphical Context en utilisant la classe Transform
� Fournit un ensemble de méthode pour effectuer
� Des translations translate(float offsetX, float offsetY)
� Des agrandissements scale(float scaleX, float scaleY)
� Des rotations rotate(float angle)
� Des transformations complexes setElements(…)
119SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : Transform
� Exemple : un effet de réflection (inspiré de Daniel Spiewak)final Display display = Display.getDefault();final Shell shell = new Shell(display, SWT.SHELL_TRI M );final Image image = new Image(display,
ReflectionExample.class.getResourceAsStream(/logo.b mp));
shell.setText("Reflection");shell.setSize(300, 200);shell.setLayout(new FillLayout());
Canvas baseCanvas = new Canvas(shell, SWT.DOUBLE_BUFF ERED);baseCanvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {// La suite dans le prochain transparent
}});
...
ReflectionExample.java du projetTransformExamples
120SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Dessiner avec Graphical Context : Transform
� Exemple (suite) : un effet de réflection (Daniel Spiewak)
Pattern pattern = new Pattern(display, 0, 0, 0, e.h eight, display.getSystemColor(SWT.COLOR_GRAY), display.getSystemColor(SWT.COLOR_BLACK));
e.gc.setBackgroundPattern(pattern);e.gc.fillRectangle(e.x, e.y, e.width, e.height);int posX = (e.width - image.getImageData().width) / 2;int posY = 10;
e.gc.drawImage(image, posX, posY);Transform transform = new Transform(e.gc.getDevice()) ;int primaryHeight = image.getImageData().height + 10;transform.setElements(1, 0, 0, -.5f, 0, primaryHeig ht + (primaryHeight / 2));
e.gc.setAlpha(100);e.gc.setTransform(transform);e.gc.drawImage(image, posX, posY);
transform.dispose();pattern.dispose();
ReflectionExample.java du projetTransformExamples
121SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue
� SWT fournit des classes (wrapper) pour la gestion des
boîtes à outils classiques
� Boîte de messages
� Boîte de sélection de couleur
� Boîte de sélection de répertoire
� Boîte de gestion de fichier
� Boîte de sélection de fonte
� Boîte pour l’impression
� Le style de modalité pour les boîtes de dialogue pré-définies
sont obligatoirement modales
� Possibilité de créer sa propre boîte de dialogue en dérivant
de la classe Dialog
Ne dérivez pas des classes fournissant
les boîtes de dialogue communes
122SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue
Boîte de messages
Boîte de sélection de couleur
Boîte de sélection de répertoires
123SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue
Boîte de sélection de fichiers
Boîte de sélection de fontes
124SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : message
� Une boîte de message contient quatre éléments modifiables� Le texte dans la barre des titres
� Le message à afficher dans la boîte
� L’icône précisant l’importance du message
� Les types de boutons pour fermer la boîte
� Construction d’une boîte message par la classe MessageBox� MessageBox(Shell s, int type) : boite de message avec un style
� Styles d’importance : ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING, ICON_WORKING
� Styles de bouton : OK, CANCEL, YES, NO, RETRY, IGNORE
� Différentes méthodes …� setText(String t) : modifie le titre dans la barre
� int open() : affiche et retourne le code du bouton sélectionné� setMessage(String t) : message à afficher
125SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : message
� Exemple : afficher une boîte de dialogue message
public class MessageDialogExample {...public MessageDialogExample(Shell shell) {
...MessageBox mb = new MessageBox(shell, SWT.ICON_QUEST ION | SWT.YES | SWT.NO
| SWT.CANCEL);mb.setMessage("Voulez-vous apprendre SWT?");mb.setText("Question à 2 sous");int value = mb.open();if (value == SWT.YES) {
System.out.println("Yes");} else if (value == SWT.NO) {
System.out.println("No");} else {
System.out.println("Cancel");}...
}}
Pas de logique dans les noms des méthodes !! Pourquoi setText(…) pour modifier le titre d’une fenêtre????
MessageDialogExample.java du projet DialogExamples
126SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : sélection de couleur
� Affiche un spectre des couleurs pour en choisir une
� Construction d’une boîte de couleur par la classe ColorDialog� ColorDialog(Shell s) : construit une boîte associée au Shell s
� Cette boîte manipule (pour la sélection utilisateur) un objet composantes couleurs de classe RGB� RGB(int red, int green, int blue)
� Objet couleur défini par la classe Color� Color(Device d, RGB rgb)
� Différentes méthodes …� RGB getRGB() : retourne la couleur sélectionnée (NULL si pas de
sélection)
� setRGB(RGB rgb) : sélectionne une couleur pour l’ouverture� RGB open() : affiche et retourne la couleur sélectionnée� setText(String p) : modifie le titre
127SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : sélection de couleur
� Exemple : afficher une boîte de sélection de couleurpublic class ColorDialogExample {
...public ColorDialogExample(shell shell) {
...ColorDialog cd = new ColorDialog(shell);cd.setText("Choisir une couleur");RGB value = cd.open();Color colorBackGround = new Color(shell.getDisplay(), value);myButton.setBackground(colorBackGround);colorBackGround.dispose();...
}}
ColorDialogExample.java du projet DialogExamples
128SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : sélection de répertoire
� Cette boîte permet la sélection d’un répertoire avec
possibilité d’en créer un s’il n’existe pas
� Construction d’une boîte de sélection de répertoire par la
classe DirectoryDialog
� DirectoryDialog(Shell s) : construit une boîte associé à s
� Différentes méthodes …
� String getFilterPath() : retourne le répertoire sélectionné
� setMessage(String p) : modifie le message contenu dans la boîte
� setText(String p) : modifie le message de la barre des titres
� String open() : affiche la boîte et retourne le répertoire sélectionné
129SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Les boîtes de dialogue : sélection de répertoire
� Exemple : afficher une boîte de sélection de répertoirepublic class DirectoryDialogExample {
...public DirectoryDialogExample() {
...DirectoryDialog dd = new DirectoryDialog(shell);dd.setText("Choisir un répertoire");dd.setMessage("Veuillez sélectionner un répertoire" );String value = mb.open();System.out.println(value);...
}}
DirectoryDialogExample.java du projet DialogExamples
130SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes boîtes de dialogue : gestion de fichier
� Cette boîte permet la sélection d’un fichier pour l’ouverture
et la sauvegarde
� Le style permet de paramétrer une boîte d’ouverture ou de
sauvegarde
� OPEN : pour l’ouverture d’un fichier
� MULTI : pour l’ouverture de plusieurs fichiers
� SAVE : pour la sauvegarde d’un fichier
� Construction d’une boîte par la classe FileDialog
� FileDialog(Shell s) : construit une boîte associé à s
� FileDialog(Shell s, int ps) : construit une boîte avec le style ps
131SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes boîtes de dialogue : gestion de fichier
� Différentes méthodes …� String getFileName() : retourne le fichier traité
� String[] getFileName() : retourne les fichiers (pour le style MULTI)
� String open() : affiche la boîte et retourne le fichier traité
� setText(String p) : modifie le titre de la boîte de gestion de fichier
� Possibilité de filtrer les fichiers qui apparaîtront dans la boîte� setFilterNames(String[] names) : description des noms de filtres
� setFilterExtensions(String[] ex) : description des filtres
� Exemples manipulation des filtresopenSaveDialog.setFilterNames(new String[] {
"Image BMP (*.bmp)","Image JPG (*.jpg)"
});openSaveDialog.setFilterExtensions(new String[] {
"*.bmp","*.jpg"
});
Définition des noms de filtres
Définition des filtres
132SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes boîtes de dialogue : gestion de fichier
� Exemple : afficher une boîte de gestion de fichierspublic class FileDialogExample {
...public FileDialogExample() {
...Filedialog fd = new Filedialog(shell, SWT.OPEN);fd.setFilterNames(new String[] {
"Image BMP (*.bmp)","Image JPG (*.jpg)"
});fd.setFilterExtensions(new String[] {
"*.bmp","*.jpg"
});fd.setText("Choisir un fichier");String value = fd.open();System.out.println(value);...
}}
FileDialogExample.java du projetDialogExamples
133SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes boîtes de dialogue : sélection de fonte
� Cette boîte permet la sélection d’une fonte
� Construction d’une boîte par la classe FontDialog� FontDialog(Shell s) : construit une boîte associé à s
� Cette boîte manipule (pour la sélection utilisateur) un objet de classe FontData pour manipuler une fonte
� La couleur de la fonte n’est pas stockée dans FontData et par conséquent la boîte retourne un objet RGB
� Différentes méthodes …� FontData[] getFontList() : contient la liste des données d’une fonte
� setFontList(FontData[] p) : modifie les informations d’une fonte
� FontData open() : affiche la boîte et retourne la fonte
� RGB getRGB() : retourne la couleur sélectionnée
� setText(String t) : modifie le titre de la boîte
134SWT - M. Baron - Page
keul
keul
.blo
gspo
t.comLes boîtes de dialogue : sélection de fonte
� Exemple : afficher une boîte de sélection de fontepublic class FontDialogExample {
...public FontDialogExample() {
...FontDialog fd = new FontDialog(shell);fd.setText("Choisir une fonte");FontData value = fd.open();// Affichie le nom de la police utiliséeSystem.out.println(value.getName());...
}}
FontDialogExample.java du projet DialogExamples
135SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Le processus créé par le Display est un processus graphique
appelé UI-thread
� UI-thread s’occupe de lire et dispatcher les événements
issus du système d’exploitation puis d’invoquer les écouteurs
associés à ces événements
� Pour les traitements important à effectuer, utiliser un thread
séparé (noté task-thread) au UI-thread de manière à ce que
le UI-thread puisse traiter les événements du système
� Seul le UI-thread peut manipuler les éléments graphiques et
tout accès à l’extérieur du UI-thread engendre une
exception de type : org.eclipse.swt.SWTException
136SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Pour résoudre le problème de SWTException il faut inclure les appels graphiques dans le UI-thread
� Display fournit deux méthodes
� syncExec(Runnable r) : appel synchrone
� asyncExec(Runnable r) : appel asynchrone
� Runnable est un objet thread en charge de la modification graphique contenant une méthode run()� void run() { code qui modifie l’IHM }
� Avec un appel synchrone task-thread est en attente tant que le code contenu dans le run n’est pas terminé
� Avec un appel asynchrone task-thread continue à s’exécuter en parallèle du code contenu dans le run
137SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Deux exemples qui présentent un appel synchrone et un appel asynchrone
� Exemple pour l’appel synchrone� Un Thread en charge de gérer un compteur (3 à 0)
� A chaque occurrence une boîte de message est lancée de manière synchrone
� Tant que la boîte de message n’est pas fermé le thread compteur est bloqué
� Exemple pour l’appel asynchrone� Un Thread qui gère un compteur (100 à 0)
� A chaque occurrence une barre de progression est avertie de manière asynchrone
� La modification de la barre de progression n’influence pas le compteur (l’IHM ne bloque pas le modèle)
138SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Exemple : affichage d’une boîte de dialogue pour un appel synchrone
public class SynchroneExample {private Timer t;public SynchroneExample() {
final Display display = new Display();final Shell shell = new Shell(display);shell.setLayout(new FillLayout(SWT. VERTICAL));Button myButton = new Button(shell, SWT. FLAT);myButton.setText("Go");myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {if (t != null) {
t.cancel();}t = new Timer();t.schedule(new TimerTask() {
// Voir transparent suivant ...}, 0, 1*1000);
}});...
}...
}
SynchroneExample.java du projet DialogExamples
139SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Exemple (suite): affichage d’une boîte de dialogue pour un appel synchrone
t.schedule(new TimerTask() {int nbrRepetitions = 3;
public void run() {if (nbrRepetitions > 0) {
System. out.println("Ca bosse dur!");nbrRepetitions--;
display.syncExec(new Runnable() {public void run() {
MessageBox d = new MessageBox(shell, SWT. YES);d.setText("Mon Titre");d.setMessage("");d.open();
}});System. out.println("Ici");
} else {System. out.println("Terminé!");t.cancel();
}}
}, 0, 1*1000);
140SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Exemple : barre de progression pour un appel asynchrone
public class ASynchroneExample {private Timer t;public ASynchroneExample() {
...Button myButton = new Button(shell, SWT. FLAT);final ProgressBar myProgressBar = new ProgressBar(shell, SWT.NONE);myProgressBar.setMaximum(100);myProgressBar.setMinimum(0);myProgressBar.setSelection(100);myButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {if (t != null) {
t.cancel();}t = new Timer();t.schedule(new TimerTask() {
// Voir transparent suivant ...}, 0, 1 * 10);
}});...
}...
}
ASynchroneExample.java du projet DialogExamples
141SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
UI-thread et SWTException
� Exemple (suite) : barre de progression pour un appel asynchrone
t.schedule(new TimerTask() {int nbrRepetitions = 100;
public void run() {display.asyncExec(new Runnable(){
public void run() {myProgressBar.setSelection(nbrRepetitions);
}});
if (nbrRepetitions > 0) {nbrRepetitions--;
} else {System. out.println("Terminé");t.cancel();
}}
}, 0, 1 * 10);
ASynchroneExample.java du projet DialogExamples
142SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� L’API SWT permet d’intégrer des composants basés sur la
boîte à outils Swing
� L’avantage est de pouvoir intégrer des
composants qui n’existe pas dans la boîte à outils SWT
� L’inconvénient est de se trouver avec des composants
hétérogènes dans la manière de les utiliser
� Abonnement à des écouteurs différents
� Gestion du « dessin » différent
� Agents de placement différents
� Bref beaucoup de différences
Evitez tant que possible de mixer des composants
Swing avec SWT
143SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Exemple : intégrer des composants JFreeCharts et JGraph
JGraph
JFreeCharts
144SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� L’intégration de composants Swing se fait par l’intermédiaire de la couche bas niveau de Swing c’est-à-dire via AWT
� Principe général� Le point d’entrée de Swing vers SWT est obtenu par l’intermédiaire
d’une Frame (java.awt.frame)
� Tous composants Swing doit être contenus dans une Frame (ou plusieurs)
� Il faut voir la Frame comme un conteneur au même titre que leComposite en SWT
� L’handle de la Frame (identifiant) est récupéré puis utilisé par SWT pour ajouter le contenu de la Frame vers un Composite SWT
Exemple : il est possible d’intégrer n’importe quelle application Win32 dans du SWT par l’intermédiaire des
handles de fenêtre : à suivre …
145SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� L’API SWT fournit une API spécifique pour l’intégration de
composants Swing
� package : org.eclipse.swt.awt
� classe : SWT_AWT
� Les méthodes de la classe SWT_AWT
� static Frame new_Frame(Composite parent) : construit une Frame
contenant les composants Swing, parent est le conteneur SWT qui
contiendra la Frame créée
� La Frame créée est la racine des composants Swing
� Le Composite parent doit avoir le style SWT.EMBEDDED
146SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Exemple : SWT + Swing = SWingT ?public class SWTAWTExample {
...public SWTAWTExample() {
Display display = new Display();Shell shell = new Shell(display);GridLayout layout = new GridLayout(1, false);shell.setLayout(layout);shell.setText("SWT and Swing/AWT Example");Label separator1 = new Label(shell, SWT.NONE);separator1.setText("Mon Message en SWT");Composite awtComp = new Composite(shell,SWT.EMBEDDED );GridData myGridData = new GridData(GridData.FILL_BOTH );awtComp.setLayoutData(myGridData);Frame awtFrame = SWT_AWT.new_Frame(awtComp);JTextField textField = new JTextField("Saisir une val eur dans du Swing");awtFrame.add(textField);...
}}
Composant SwingComposant SWT
SWTAWTExample.java du projetSWTAndSwingEamples
147SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Exemple : Winrar dans une Shell � Utilisation de la classe org.eclipse.swt.internal.win32.OS
Shell SWT
Button SWT
Application WINRAR
Peut très bien être du natif MAC
OS, Linux, …
148SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Une des grandes forces de la boîte à outils Swing concerne l’API Java 2D
� Le portage de composants Swing vers SWT reste facile, mais qu’en est-il d’un code Java 2D à migrer ou adapter ?
� Une solution est fournie par la classe Graphics2DRenderer� www-128.ibm.com/developerworks/java/library/j-2dswt/
� Principe
� Construire un objet Graphics2DRenderer
� Récupérer le GC d’un composant SWT (par exemple un Canvas)
� Initialiser l’objet Graphics2DRenderer avec le GC
� Utiliser l’API Java2D de Sun
� Générer un rendu des opérations Java2D dans le GC par l’intermédiaire du Graphics2DRenderer
149SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Principe de fonctionnement de Graphics2DRenderer
150SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
� Une autre façon de faire cohabiter des composants Swing est d’utiliser la librairie SwingWT
� SwingWT fournit une re-implémentation des composants Swing en SWT
� Adresse : swingwt.sourceforge.net� La logique de l’API Swing est respectée
� javax.swing.JButton en Swing
� swingwt.swing.JButton en SwingWT
� Avantages� Fournir des plug-ins Eclipse en utilisant les composants types Swing
� Refactoring très facile d’anciennes applications Swing
� Compilation en code natif avec GCJ
� Inconvénients� Retard par rapport aux nouveautés des JDK
151SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Cohabitation entre composants Swing et SWT
Demo SwingSet en utilisant SwintWT
(refactoringimmédiat de l’application)
152SWT - M. Baron - Page
keul
keul
.blo
gspo
t.com
Bilan …
� Premières impressions …
� Pas aussi souple que Swing (limitée par rapport au système hôte)
� Difficile de réaliser des effets graphiques (absence de GlassPane :-( )
� Venant du monde Swing la tentation d’incorporer des composants
Swing dans du SWT est forte (SWT pas aussi fournie en composant)
� Sur le net, peu de « hacker » SWT ;-)
� Parfois, l’API SWT n’est pas un modèle de programmation !!!
� Les choses non étudiées, prochainement …
� La gestion de l’impression
� Approfondir Graphical Context (Transformation [scale, rotate, …])
� Appels à des fonctions systèmes via JNI/JNA et la classe OS
� …
top related