Niveau : | Intermédiaire |
La première API pour développer des interfaces graphiques portables d'un système à un autre en Java est AWT. Cette API repose sur les composants graphiques du système sous-jacent ce qui lui assure de bonnes performances. Malheureusement, ces composants sont limités dans leur fonctionnalité car ils représentent le plus petit dénominateur commun des différents systèmes concernés.
Pour pallier ce problème, Sun a proposé une nouvelle API, Swing. Cette Api est presque exclusivement écrite en Java, ce qui assure sa portabilité. Swing possède aussi d'autres points forts, telles que des fonctionnalités avancées, la possibilité d'étendre les composants, une adaptation du rendu de composants, etc ... Swing est une API mature, éprouvée et parfaitement connue. Malheureusement, ses deux gros défauts sont sa consommation en ressource machine et la lenteur d'exécution des applications qui l'utilisent.
SWT propose une approche intermédiaire : utiliser autant que possible les composants du système et implémenter les autres composants en Java. SWT est écrit en Java et utilise la technologie JNI pour appeler les composants natifs. SWT utilise autant que possible les composants natifs du système lorsqu'ils existent, sinon ils sont réécrits en pur Java. Les données de chaque composant sont aussi stockées autant que possible dans le composant natif, limitant ainsi les données stockées dans les objets Java correspondant.
Ce chapitre contient plusieurs sections :
Une partie de SWT est livrée sous la forme d'une bibliothèque dépendante du système d'exploitation et d'un fichier .jar lui aussi dépendant du système. Toutes les fonctionnalités de SWT ne sont implémentées que sur les systèmes où elles sont supportées (exemple, l'utilisation des ActiveX n'est possible que sur le portage de SWT sur les systèmes Windows).
Les trois avantages de SWT sont donc la rapidité d'exécution, des ressources machines moins importantes lors de l'exécution et un rendu parfait des composants graphiques selon le système utilisé puisqu'il utilise des composants natifs. Cette dernière remarque est particulièrement vraie pour des environnements graphiques dont l'apparence est modifiable.
Malgré cette dépendance vis à vis du système graphique de l'environnement d'exécution, l'API de SWT reste la même quelque soit la plate-forme utilisée.
En plus de dépendre du système utilisé lors de l'exécution, SWT possède un autre petit inconvénient. N'utilisant pas de purs objets java, il n'est pas possible de compter sur le ramasse miette pour libérer la mémoire des composants créés manuellement. Pour libérer cette mémoire, il est nécessaire d'utiliser la méthode dispose() pour les composants instanciés lorsque ceux-ci ne sont plus utiles.
Pour faciliter ces traitements, l'appel de la méthode dispose() d'un composant entraîne automatiquement l'appel de la méthode dispose() des composants qui lui sont rattachés. Il faut toutefois rester vigilant lors de l'utilisation de certains objets qui ne sont pas des contrôles tels que les objets de type Font ou Color, qu'il convient de libérer explicitement sous peine de fuites de mémoire.
Les règles à observer pour la libération des ressources sont :
Attention, l'utilisation d'un objet dont la méthode dispose() a été appelée induira un résultat imprévisible.
Ainsi SWT pose à nouveau la problématique concernant la dualité entre la portabilité (Write Once Run Anywhere) et les performances.
SWT se fonde sur trois concepts classiques dans le développement d'une interface graphique :
La structure d'une application SWT est la suivante :
La version de SWT utilisée dans ce chapitre est la 2.1.
SWT est regroupé dans plusieurs packages :
Package |
Rôle |
org.eclipse.swt |
Package de base qui contient la définition de constantes et d'exceptions |
org.eclipse.swt.accessibility |
|
org.eclipse.swt.custom |
Contient des composants particuliers |
org.eclipse.swt.dnd |
Contient les éléments pour le support du « cliqué / glissé » |
org.eclipse.swt.events |
Contient les éléments pour la gestion des événements |
org.eclipse.swt.graphics |
Contient les éléments pour l'utilisation des éléments graphiques (couleur, polices, curseur, contexte graphique, ...) |
org.eclipse.swt.layout |
Contient les éléments pour la gestion de la présentation |
org.eclipse.swt.ole.win32 |
Contient les éléments pour le support d'OLE 32 sous Windows |
org.eclipse.swt.printing |
Contient les éléments pour le support des impressions |
org.eclipse.swt.program |
|
org.eclipse.swt.widgets |
Contient les différents composants |
L'exemple de cette section affiche simplement bonjour dans une fenêtre.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.*;
public class TestSWT1 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Label label = new Label(shell, SWT.CENTER);
label.setText("Bonjour!");
label.pack();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
label.dispose();
}
}
Pour exécuter cet exemple sous Windows, il faut que le fichier swt.jar correspondant à la plate-forme Windows soit inclus dans le classpath et que l'application puisse accéder à la bibliothèque swt-win32-2135.dll.
Cette classe définit un certain nombre de constantes concernant les styles. Les styles sont des comportements ou des caractéristiques définissant l'apparence du composant. Ces styles sont directement fournis dans le constructeur d'une classe encapsulant un composant.
Toute application SWT doit obligatoirement instancier un objet de type Display. Cet objet assure le dialogue entre l'application et le système graphique du système d'exploitation utilisé.
Exemple : |
Display display = new Display();
La méthode la plus importante de la classe Display est la méthode readAndDispatch() qui lit les événements dans la pile du système graphique natif pour les diffuser à l'application. Elle renvoie true s'il y a encore des traitements à effectuer sinon elle renvoie false.
La méthode sleep() permet de mettre en attente le thread d'écoute d'événements jusqu'à l'arrivée d'un nouvel événement.
Il est absolument nécessaire lors de la fin de l'application de libérer les ressources allouées par l'objet de type Display en appelant sa méthode dispose().
L'objet Shell représente une fenêtre gérée par le système graphique du système d'exploitation utilisé.
Un objet de type Shell peut être associé à un objet de type Display pour obtenir une fenêtre principale ou être associé à un autre objet de type Shell pour obtenir une fenêtre secondaire.
La classe Shell peut utiliser plusieurs styles : BORDER,H_SCROLL, V_SCROLL, CLOSE, MIN, MAX, RESIZE, TITLE, SHELL_TRIM, DIALOG_TRIM
BORDER : une fenêtre avec une bordure sans barre de titre
|
|
TITLE : une fenêtre avec une barre de titre
|
|
CLOSE : une fenêtre avec un bouton de fermeture
|
|
MIN : une fenêtre avec un bouton pour iconiser
|
|
MAX : une fenêtre avec un bouton pour agrandir au maximum
|
|
RESIZE : une fenêtre dont la taille peut être modifiée
|
|
SHELL_TRIM : groupe en une seule constante les styles CLOSE, TITLE, MIN, MAX et RESIZE | |
DIALOG_TRIM : groupe en une seule constante les styles CLOSE, TITLE et BORDER |
|
APPLICATION_MODAL : | |
SYSTEM_MODAL : |
La méthode setSize() permet de préciser la taille de la fenêtre.
La méthode setText() permet de préciser le titre de la fenêtre.
Exemple : centrer la fenêtre sur l'écran |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
public class TestSWT1 {
public static void centrerSurEcran(Display display, Shell shell) {
Rectangle rect = display.getClientArea();
Point size = shell.getSize();
int x = (rect.width - size.x) / 2;
int y = (rect.height - size.y) / 2;
shell.setLocation(new Point(x, y));
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(340, 100);
centrerSurEcran(display, shell);
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Les composants peuvent être regroupés en deux grandes familles :
Une application SWT est une hiérarchie de composants dont la racine est un objet de type Shell.
Certaines caractéristiques comme l'apparence ou le comportement d'un contrôle doivent être fournies au moment de leur création par le système graphique. Ainsi, chaque composant SWT possède une propriété nommée style fournie en paramètre du constructeur.
Plusieurs styles peuvent être combinés avec l'opérateur | . Cependant certains styles sont incompatibles entre-eux pour certains composants.
La classe Control définit trois styles : BORDER, LEFT_TO_RIGHT et RIGHT_TO_LEFT
Le seul constructeur de la classe Control nécessite aussi de préciser le composant père sous la forme d'un objet de type Composite. L'association avec le composant père est obligatoire pour tous les composants lors de leur création.
La classe Control possède plusieurs méthodes pour enregistrer des listeners pour certains événements. Ces événements sont : FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter, MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize.
Elle possède aussi plusieurs méthodes dont les principales sont :
Nom | Rôle |
boolean forceFocus() | Force le focus au composant pour lui permettre de recevoir les événements clavier |
Display getDisplay() | Renvoie l'objet Display associé au composant |
Shell getShell() | Renvoie l'objet Shell associé au composant |
void pack() | Recalcule la taille préférée du composant |
void SetEnabled() | Permet de rendre actif le composant |
void SetFocus() | Donne le focus au composant pour lui permettre de recevoir les événements clavier |
void setSize() | Permet de modifier la taille du composant |
void setVisible() | Permet de rendre visible ou non le composant |
La classe Button représente un bouton cliquable.
La classe Button définit plusieurs styles : BORDER, CHECK, PUSH, RADIO, TOGGLE, FLAT, LEFT, RIGHT, CENTER, ARROW (avec UP, DOWN)
NONE : un bouton par défaut
|
|
BORDER : met une bordure autour du bouton
|
|
CHECK : une case à cocher
|
|
RADIO : un bouton radio
|
|
PUSH : un bouton standard (valeur par défaut)
|
|
TOGGLE : un bouton pouvant conservé un état enfoncé
|
|
ARROW : bouton en forme de flèche (par défaut vers le haut)
|
|
RIGHT : aligne le contenu du bouton sur la droite
|
|
LEFT : aligne le contenu du bouton sur la gauche
|
|
CENTER : centre le contenu du bouton
|
|
FLAT : le bouton apparaît en 2D
|
Ce contrôle permet d'afficher un libellé ou une image
La classe Label possède plusieurs styles : BORDER, CENTER, LEFT, RIGHT, WRAP, SEPARATOR (avec HORIZONTAL, SHADOW_IN, SHADOW_OUT, SHADOW_NONE, VERTICAL)
NONE : un libellé par défaut
|
|
BORDER : ajouter une bordure autour du libellé
|
|
CENTER : permet de centrer le libellé
|
|
SEPARATOR et VERTICAL : une barre verticale
|
|
SEPARATOR et HORIZONTAL : une barre horizontale
|
|
SHADOW_IN :
|
|
SHADOW_OUT :
|
Cette classe possède plusieurs méthodes dont les principales sont :
Nom | Rôle |
void setAlignment(int) | Permet de préciser l'alignement des données du contrôle |
void setImage(Image) | Permet de préciser une image affichée par le contrôle |
void setText(string) | Permet de préciser le texte du contrôle |
Ce contrôle est une zone de saisie de texte.
La classe Text possède plusieurs styles : BORDER, SINGLE, READ_ONLY, LEFT, CENTER, RIGHT, WRAP, MULTI (avec H_SCROLL, V_SCROLL)
NONE : une zone de saisie sans bordure
|
|
BORDER : une zone de saisie avec bordure
|
|
MULTI, SWT.H_SCROLL, SWT.V_SCROLL : une zone de saisie avec bordure
|
|
READ_ONLY : une zone de saisie en lecture seule |
Cette classe possède plusieurs méthodes dont les principales sont :
Nom | Rôle |
void setEchoChar(char) | Caractère affiché lors de la frappe d'une touche |
void setTextLimit(int) | Permet de préciser le nombre maximum de caractères saisissables |
void setText(string) | Permet de préciser le contenu de la zone de texte |
void setEditable(boolean) | Permet de rendre le contrôle éditable ou non |
SWT permet de créer des composants de type liste et liste déroulante.
Ce contrôle est une liste déroulante dans laquelle l'utilisateur peut sélectionner une valeur dans une liste d'éléments prédéfinis ou saisir un élément.
La classe Combo définit trois styles : BORDER, DROP_DOWN, READ_ONLY, SIMPLE
BORDER : une liste déroulante
|
|
READ_ONLY : une liste déroulante ne permettant que la sélection (saisie d'un élément impossible)
|
|
SIMPLE : zone de saisie et une liste
|
Ce contrôle est une liste qui permet de sélectionner un ou plusieurs éléments.
La classe List possède plusieurs styles : BORDER, H_SCROLL, V_SCROLL, SINGLE, MULTI
BORDER : une liste
|
|
V_SCROLL : une liste avec une barre de défilement
|
|
MULTI : une liste avec sélection de plusieurs éléments
|
La méthode add() permet d'ajouter un élément à la liste sous la forme d'une chaînes de caractères.
La méthode setItems() permet de fournir les éléments de la liste sous la forme d'un tableau de chaînes de caractères.
Exemple : |
List liste = new List(shell, SWT.V_SCROLL | SWT.MULTI);
liste.setItems(new String[] {"element 1", "element 2", "element 3", "element 4"});
liste.setSize(100,41);
SWT permet la création de menus principaux et de menus déroulants. La création de ces menus met en oeuvre deux classes : Menu, MenuItem
Ce contrôle est un élément du menu qui va contenir des options
La classe Menu possède plusieurs styles : BAR, DROP_DOWN, NO_RADIO_GROUP, POP_UP
BAR : le menu principal d'une fenêtre
|
|
POP_UP : un menu contextuel
|
|
DROP_DOWN : un sous menu | |
NO_RADIO_GROUP : |
Ce contrôle est une option d'un menu.
La classe MenuItem possède plusieurs styles : CHECK, CASCADE, PUSH, RADIO, SEPARATOR
CASCADE : une option de menu qui possède un sous menu PUSH : une option de menu
|
|
CHECK : une option de menu avec un état coché ou non
|
|
Radio : une option de menu sélectionnable parmi un ensemble
|
|
SEPARATOR : pour séparer les options d'un menu
|
La méthode setText() permet de préciser le libellé de l'option de menu.
La méthode setAccelerator() permet de préciser un raccourci clavier.
|
SWT propose un contrôle pour l'affichage d'une barre de progression et deux contrôles pour la sélection d'une valeur numérique dans une plage de valeur.
Ce contrôle est une barre de progression.
La classe ProgressBar possède plusieurs styles : BORDER, INDETERMINATE, SMOOTH, HORIZONTAL, VERTICAL
HORIZONTAL :
|
|
SMOOTH :
|
|
INDETERMINATE : la barre de progression s'incrémente automatiquement et revient au début indéfiniment
|
Les méthodes setMinimum() et setMaximum() permettent respectivement de préciser les valeurs minimale et maximale du contrôle.
La méthode setSelection() permet de positionner la valeurs courante de l'indicateur.
Ce contrôle permet de faire une sélection dans une plage de valeurs numériques.
La classe Scale possède trois styles : BORDER, HORIZONTAL, VERTICAL
HORZONTAL :
|
|
VERTICAL :
|
|
BORDER :
|
Les méthodes setMinimum() et setMaximum() permettent respectivement de préciser les valeurs minimale et maximale du contrôle.
La méthode setSelection() permet de positionner le curseur dans la plage de valeurs à la valeur fournie en paramètre.
La méthode setPageIncrement() permet de préciser la valeur fournie en paramètre d'incrémentation d'une page
Exemple :
Scale scale = new Scale(shell,SWT.HORIZONTAL);
|
Ce contrôle permet de sélectionner une valeur dans une plage de valeurs numériques.
La classe Slider possède trois styles : BORDER, HORIZONTAL, VERTICAL
BORDER :
|
|
VERTICAL :
|
Les méthodes setMinimum() et setMaximum() permettent respectivement de préciser les valeurs minimale et maximale du contrôle.
La méthode setSelection() permet de positionner le curseur dans la plage de valeurs à la valeur fournie en paramètre.
La méthode setPageIncrement() permet de préciser la valeur d'incrémentation d'une page du contrôle.
La méthode setThumb() permet de préciser la taille du curseur.
Exemple :
Slider slider = new Slider(shell,SWT.HORIZONTAL);
|
SWT propose la création de composants de type onglets mettant en oeuvre deux classes : TabFolder et TabItem
Ce contrôle est un ensemble d'onglets.
NONE :
|
|
BORDER : un ensemble d'onglets avec une bordure
|
Ce contrôle est un onglet d'un ensemble d'onglets
La méthode setControl() ne permet d'insérer qu'un seul contrôle dans un onglet mais ce contrôle peut être de type Composite et regrouper différents éléments.
Exemple : |
TabFolder tabfolder = new TabFolder(shell, SWT.NONE);
tabfolder.setSize(200,100);
TabItem onglet1 = new TabItem(tabfolder, SWT.NONE);
onglet1.setText("Onglet 1");
TabItem onglet2 = new TabItem(tabfolder, SWT.NONE);
onglet2.setText("Onglet 2");
Composite pageOnglet1 = new Composite(tabfolder, SWT.NONE);
Text text1 = new Text(pageOnglet1, SWT.BORDER);
text1.setText("mon texte");
text1.setBounds(10,10,100,25);
Button button1 = new Button(pageOnglet1, SWT.BORDER);
button1.setText("Valider");
button1.setBounds(10,40,100,25);
onglet1.setControl(pageOnglet1);
SWT permet la création d'un contrôle de type tableau pour afficher et sélectionner des données en mettant en oeuvre trois classes : Table, TableColumn et TableItem.
Ce contrôle permet d'afficher et de sélectionner des éléments sous la forme d'un tableau.
La classe Table possède plusieurs styles : BORDER, H_SCROLL, V_SCROLL, SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION
BORDER :
|
|
MULTI : permet la sélection de plusieurs éléments dans la table
|
|
CHECK : une table avec une case à cocher pour chaque ligne
|
|
FULL_SELECTION : la ou les lignes sélectionnées sont entièrement mises en valeur
|
|
HIDE_SELECTION : seule la première colonne sélectionnée est mise en valeur |
La méthode setHeaderVisible() permet de préciser si l'en-tête de la table doit être affiché ou non : par défaut il est non affiché (false).
La méthode setLinesVisible() permet de préciser si les lignes de la table doivent être affichées ou non : par défaut elles ne sont pas affichées (false).
Ce contrôle est une colonne d'un contrôle Table
La classe TableColumn possède trois styles : LEFT, RIGHT, CENTER
LEFT : alignement de la colonne sur la gauche (valeur par défaut) | |
RIGHT : alignement de la colonne sur la droite
|
|
CENTER : alignement centré de la colonne
|
Bizarrement, seul le style LEFT semble pouvoir s'appliquer à la première colonne de la table.
La méthode setWidth() permet de préciser la largeur de la colonne
La méthode setText() permet de préciser le libellé d'en-tête de la colonne
La méthode setResizable() permet de préciser si la colonne peut être redimensionnée ou non.
Ce contrôle est une ligne d'un contrôle Table
La classe TableItem ne possède aucun style.
Il existe plusieurs surcharges de la méthode setText() pour fournir à chaque ligne les données de ses colonnes.
Une surcharge de cette méthode permet de fournir les données sous la forme d'un tableau de chaînes de caractères.
Exemple : |
ligne1.setText(new String[] {"valeur 1 1","valeur 1 2"});
Une autre surcharge de cette méthode permet de préciser le numéro de la colonne et le texte. La première colonne possède le numéro 0.
Exemple : modifier la valeur de la première cellule de la ligne |
ligne4.setText(0 ,"valeur 2 2");
La méthode setCheck() permet de cocher ou non la case associée à la ligne si la table possède le style CHECK.
SWT permet la création d'un composant de type arbre en mettant en oeuvre les classes Tree et TreeItem.
Ce contrôle affiche et permet de sélectionner des données sous la forme d'une arborescence
La classe Tree possède plusieurs styles : BORDER, H_SCROLL, V_SCROLL, SINGLE, MULTI, CHECK
SINGLE : un arbre avec sélection unique
|
|
BORDER : arbre avec une bordure
|
|
H_SCROLL et V_SCROLL : arbre avec si nécessaire une barre de défilement respectivement horizontal et vertical
|
|
MULTI : un arbre avec sélection multiple possible
|
|
CHECK : un arbre avec une case à cocher devant chaque élément
|
Ce contrôle est un élément d'une arborescence
Cette classe ne possède pas de style particulier.
Pour ajouter un élément racine à l'arbre, il suffit de passer l'arbre en tant qu'élément conteneur dans le constructeur.
Pour ajouter un élément fils à un élément, il suffit de passer l'élément père en tant qu'élément conteneur dans le constructeur.
Il existe un constructeur qui attend un troisième paramètre permettant de préciser la position de l'élément.
Exemple : |
|
Ce contrôle est une barre de défilement
La classe ScrollBar possède deux styles : HORIZONTAL, VERTICAL
SWT permet de dessiner des formes graphiques en mettant en oeuvre la classe GC et la classe Canvas.
Ce contrôle est utilisé pour dessiner des formes graphiques
La classe Canvas définit plusieurs styles : BORDER, H_SCROLL, V_SCROLL, NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP
BORDER : une zone de dessin avec bordure
|
Cette classe encapsule un contexte graphique dans lequel il va être possible de dessiner des formes.
Pour réaliser ces opérations, la classe GC propose de nombreuses méthodes.
Attention : il est important d'appeler la méthode open() de la fenêtre avant de réaliser des opérations de dessin sur le contexte.
Ne pas oublier le libérer les ressources allouées à la classe GC en utilisant la méthode dispose() si l'objet de GC est explicitement instancié dans le code.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class TestSWT21 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(420,420);
Canvas canvas = new Canvas(shell, SWT.NONE);
canvas.setSize(200,200);
canvas.setLocation(10,10);
shell.pack();
shell.open();
GC gc = new GC(canvas);
gc.drawText("Bonjour",20,20);
gc.drawLine(10,10,10,100);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.drawOval(60,60,60,60);
gc.dispose();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Dans cette exemple, le dessin est réalisé une seule fois au démarrage, il n'est donc pas redessiné si nécessaire (fenêtre partiellement ou complètement masquée, redimensionnement, ...). Pour résoudre ce problème, il faut mettre les opérations de dessin en réponse à un événement de type PaintListener.
Cette classe encapsule une couleur définie dans le système graphique.
Elle possède deux constructeurs qui attendent en paramètre l'objet de type Display et soit un objet de type RGB, soit trois entiers représentant les valeurs des couleurs rouge, vert et bleu.
La classe RGB encapsule simplement les trois entiers représentant les valeurs des couleurs rouge, vert et bleu.
Exemple : |
Color couleur = new Color(display,155,0,0);
Color couleur = new Color(display, new RGB(155,0,0));
Remarque : il ne faut pas oublier d'utiliser la méthode dispose() pour libérer les ressources du système allouées à cet objet une fois que celui-ci n'est plus utilisé.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class TestSWT22 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(200, 200);
Color couleur = new Color(display,155,0,0);
shell.setBackground(couleur);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
couleur.dispose();
display.dispose();
}
}
Cette classe encapsule une police de caractères définie dans le système graphique.
La classe Font peut utiliser plusieurs styles : NORMAL, BOLD et ITALIC
Il existe plusieurs constructeurs dont le plus simple à utiliser nécessite en paramètre l'objet display, le nom de la police (celle-ci doit être présente sur le système), la taille et le style.
Remarque : il ne faut pas oublier d'utiliser la méthode dispose() pour libérer les ressources du système allouées à cet objet une fois que celui-ci n'est plus utilisé.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.*;
public class TestSWT23 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
Font font = new Font(display, "Arial", 16, SWT.ITALIC);
Label label = new Label(shell, SWT.NONE);
label.setFont(font);
label.setText("Bonjour");
label.setLocation(10, 10);
label.pack();
shell.setSize(100, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
font.dispose();
display.dispose();
}
}
Cette classe encapsule une image au format BMP, ICO, GIF, JPEG ou PNG.
La classe Image possède plusieurs constructeurs dont le plus simple à utiliser est celui nécessitant en paramètres l'objet Display et une chaîne de caractères contenant le chemin vers le fichier de l'image
Remarque : il ne faut pas oublier d'utiliser la méthode dispose() pour libérer les ressources du système allouées à cet objet une fois que celui-ci n'est plus utilisé.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.*;
public class TestSWT24 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
Image image = new Image(display, "btn1.bmp");
Button bouton = new Button(shell, SWT.FLAT);
bouton.setImage(image);
bouton.setBounds(10, 10, 50, 50);
shell.setSize(100, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
image.dispose();
display.dispose();
}
}
Si l'application doit être packagée dans un fichier jar, incluant les images utiles, il faut utiliser la méthode getResourceAsStream() du classloader pour charger l'image.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.*;
import java.io.*;
public class TestSWT25 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
InputStream is = TestSWT25.class.getResourceAsStream("btn1.bmp");
Image image = new Image(display, is);
Button bouton = new Button(shell, SWT.FLAT);
bouton.setImage(image);
bouton.setBounds(10, 10, 50, 50);
shell.setSize(100, 100);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
image.dispose();
display.dispose();
}
}
Ce type de composant permet de contenir d'autres contrôles.
SWT propose deux contrôles de ce type : Composite et Group.
Ce contrôle est un conteneur pour d'autres contrôles.
Ce contrôle possède les styles particuliers suivants : BORDER, H_SCROLL et V_SCROLL
BORDER : permet la présence d'une bordure autour du composant
|
|
H_SCROLL : permet la présence d'une barre de défilement horizontal
|
|
V_SCROLL : permet la présence d'une barre de défilement vertical
|
Les contrôles sont ajoutés au contrôle Composite de la même façon que dans un objet de type Shell en précisant simplement que le conteneur est l'objet de type Composite.
La position indiquée pour les contrôles inclus dans le Composite est relative à l'objet Composite.
Exemple complet : |
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
public class TestSWT2 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
Composite composite = new Composite(shell, SWT.BORDER);
Color couleur = new Color(display,131,133,131);
composite.setBackground(couleur);
Label label = new Label(composite, SWT.NONE);
label.setBackground(couleur);
label.setText("Saisir la valeur");
label.setBounds(10, 10, 100, 25);
Text text = new Text(composite, SWT.BORDER);
text.setText("mon texte");
text.setBounds(10, 30, 100, 25);
Button button = new Button(composite, SWT.BORDER);
button.setText("Valider");
button.setBounds(10, 60, 100, 25);
composite.setSize(140,140);
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
couleur.dispose();
display.dispose();
}
}
Ce contrôle permet de regrouper d'autres contrôles en les entourant d'une bordure et éventuellement d'un libellé.
La classe Group possède plusieurs styles : BORDER, SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE
NONE : un cadre simple
|
|
BORDER : un cadre simple avec une bordure
|
La méthode setText() permet de préciser un titre affiché en haut à gauche du cadre.
|
SWT permet de créer des barres d'outils fixes ou flottantes.
Ce contrôle est une barre d'outils
La classe ToolBar possède plusieurs styles : BORDER, FLAT, WRAP, RIGHT, SHADOW_OUT HORIZONTAL, VERTICAL
HORIZONTAL : une barre d'outils horizontale (style par défaut)
|
|
FLAT : une barre d'outils sans effet 3D
|
|
VERTICAL : une barre d'outils verticale
|
|
BORDER : une barre d'outils avec une bordure
|
Ce contrôle est un élément d'une barre d'outils
La classe ToolItem possède plusieurs styles : PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN
PUSH : un bouton simple
|
|
CHECK : un bouton qui peut conserver son état enfoncé
|
|
SEPARATOR : un séparateur
|
|
DROP_DOWN : un bouton avec une petite flèche vers le bas |
|
RADIO : un bouton dont un seul d'un même ensemble peut être sélectionné (un ensemble est défini par des boutons de type radio qui sont adjacents)
|
Exemple : |
shell.setSize(340, 100);
final ToolBar toolbar = new ToolBar(shell, SWT.HORIZONTAL);
toolbar.setSize(shell.getSize().x, 45);
toolbar.setLocation(0, 0);
Image imageBtn1 = new Image(display, "btn1.bmp");
ToolItem btn1 = new ToolItem(toolbar, SWT.PUSH);
btn1.setImage(imageBtn1);
Image imageBtn2 = new Image(display, "btn2.bmp");
ToolItem btn2 = new ToolItem(toolbar, SWT.PUSH);
btn2.setImage(imageBtn2);
btn2.setText("Stop");
ToolItem btn3 = new ToolItem(toolbar, SWT.PUSH);
btn3.setText("Action");
ToolItem btn4 = new ToolItem(toolbar, SWT.CHECK);
btn4.setText("Check");
ToolItem btn5 = new ToolItem(toolbar, SWT.SEPARATOR);
final ToolItem btn6 = new ToolItem(toolbar, SWT.DROP_DOWN);
btn6.setText("Actions");
final Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem menu1 = new MenuItem(menu, SWT.PUSH);
menu1.setText("option 1");
MenuItem menu2 = new MenuItem(menu, SWT.PUSH);
menu2.setText("option 2");
MenuItem menu3 = new MenuItem(menu, SWT.PUSH);
menu3.setText("option 3");
btn6.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.ARROW) {
Rectangle rect = btn6.getBounds();
Point pt = new Point(rect.x, rect.y + rect.height);
pt = toolbar.toDisplay(pt);
menu.setLocation(pt.x, pt.y);
menu.setVisible(true);
}
}
});
ToolItem btn7 = new ToolItem(toolbar, SWT.RADIO);
btn7.setText("radio1");
ToolItem btn8 = new ToolItem(toolbar, SWT.RADIO);
btn8.setText("radio2");
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
imageBtn1.dispose();
imageBtn2.dispose();
display.dispose();
La classe CoolBar est une barre d'outils repositionnable. Ce contrôle doit être utilisé avec un ou plusieurs contrôles CoolItem qui représentent les éléments constitutifs de la CoolBar.
Le plus simple est d'associer une barre d'outils de type ToolBar à un de ses éléments en utilisant la méthode setControl() de la classe CoolItem.
Exemple : utilisation de la barre d'outils définie dans la section précédente |
shell.setLayout(new GridLayout());
shell.setSize(340, 100);
CoolBar coolbar = new CoolBar(shell, SWT.BORDER);
final ToolBar toolbar = new ToolBar(coolbar, SWT.FLAT);
Image imageBtn1 = new Image(display, "btn1.bmp");
ToolItem btn1 = new ToolItem(toolbar, SWT.PUSH);
btn1.setImage(imageBtn1);
Image imageBtn2 = new Image(display, "btn2.bmp");
ToolItem btn2 = new ToolItem(toolbar, SWT.PUSH);
btn2.setImage(imageBtn2);
btn2.setText("Stop");
ToolItem btn3 = new ToolItem(toolbar,SWT.PUSH);
btn3.setText("Action");
ToolItem btn4 = new ToolItem(toolbar,SWT.CHECK);
btn4.setText("Check");
ToolItem btn5 = new ToolItem(toolbar, SWT.SEPARATOR);
final ToolItem btn6 = new ToolItem(toolbar, SWT.DROP_DOWN);
btn6.setText("Actions");
final Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem menu1 = new MenuItem(menu, SWT.PUSH);
menu1.setText("option 1");
MenuItem menu2 = new MenuItem(menu, SWT.PUSH);
menu2.setText("option2");
MenuItem menu3 = new MenuItem(menu, SWT.PUSH);
menu3.setText("option3");
btn6.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.ARROW) {
Rectangle rect = btn6.getBounds();
Point pt = new Point(rect.x, rect.y + rect.height);
pt = toolbar.toDisplay(pt);
menu.setLocation(pt.x, pt.y);
menu.setVisible(true);
}
}
});
ToolItem btn7 = new ToolItem(toolbar, SWT.RADIO);
btn7.setText("radio1");
ToolItem btn8 = new ToolItem(toolbar, SWT.RADIO);
btn8.setText("radio2");
CoolItem coolItem = new CoolItem(coolbar, SWT.NONE);
coolItem.setControl(toolbar);
Point size = toolbar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
coolItem.setPreferredSize(coolItem.computeSize(size.x, size.y));
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
imageBtn1.dispose();
imageBtn2.dispose();
La classe CoolItem possède une méthode setLocked() qui attend un booléen en paramètre précisant si le contrôle peut être déplacé ou non. Cette méthode doit être appelée lors d'un clic sur un bouton de la barre pour empêcher le déplacement de celle-ci.
Lors de l'utilisation de l'API SWT, des exceptions de trois types peuvent être levées :
Dans ce mode, il faut préciser pour chaque composant, sa position et sa taille. L'inconvénient de ce mode de positionnement est qu'il réagit très mal à un changement de la taille du conteneur des composants.
SWT propose un certain nombre de gestionnaires de positionnement de contrôles (layout manager). Ceux-ci sont regroupés dans le package org.eclipse.swt.layout.
Le grand avantage de ce mode de positionnement est de laisser au LayoutManager utilisé le soin de positionner et de dimensionner chaque composant en fonction de ses règles et des paramètres qui lui sont fournis.
SWT définit quatre gestionnaires de positionnement :
Pour personnaliser finement l'arrangement des composants, des informations complémentaires peuvent être associées à chacun d'eux en utilisant un objet dédié du type RowData, GridData ou FormData respectivement pour les gestionnaires de positionnement RowLayout, GridLayout et FormLayout.
Le FillLayout est le gestionnaire de positionnement le plus simple : il organise les composants dans une colonne ou une rangée. L'espace entre les composants est calculé automatiquement par la classe FillLayout.
La classe FillLayout peut utiliser deux styles : SWT.HORIZONTAL (par défaut) et SWT.VERTICAL pour préciser le mode d'alignement
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
public class TestSWT27 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new RowLayout());
Button bouton1 = new Button(shell, SWT.FLAT);
bouton1.setText("bouton 1");
Button bouton2 = new Button(shell, SWT.FLAT);
bouton2.setText("bouton 2");
Button bouton3 = new Button(shell, SWT.FLAT);
bouton3.setText("bouton 3");
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Voici différents aperçus en cas de modification de la taille de la fenêtre.
Il n'est pas possible de mettre un espace entre le bord du conteneur et les composants avec ce gestionnaire. Il n'est pas non plus possible pour ce gestionnaire de mettre des composants sur plusieurs colonnes ou rangées.
Ce gestionnaire propose d'arranger les composants en rangées ou en colonnes. Il possède des paramètres permettant de préciser une marge, un espace, une rupture et une compression.
Propriété | Valeur par défaut | Rôle |
wrap | true | demande de faire une rupture dans la rangée s'il n'y a plus de place false : true : |
pack | true | demande à chaque composant de prendre sa taille préférée |
justify | false | justification des composants |
type | SWT.HORIZONTAL | type de mise en forme SWT.HORIZONTAL ou SWT.VERTICAL SWT.VERTICAL : |
marginLeft | 3 | taille en pixels de la marge gauche |
marginTop | 3 | taille en pixels de la marge haute |
marginRight | 3 | taille en pixels de la marge droite |
marginBottom |
3 |
taille en pixels de la marge basse |
spacing | 3 | taille en pixels entre deux cellules |
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
public class TestSWT27 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
RowLayout rowlayout = new RowLayout();
shell.setLayout(rowlayout);
Button bouton1 = new Button(shell, SWT.FLAT);
bouton1.setText("bouton 1");
Button bouton2 = new Button(shell, SWT.FLAT);
bouton2.setText("bouton 2");
Button bouton3 = new Button(shell, SWT.FLAT);
bouton3.setText("bouton 3");
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Voici différents aperçus en cas de modification de la taille de la fenêtre.
Ce gestionnaire permet d'arranger les composants dans une grille et possède plusieurs propriétés :
Propriété | Valeur par défaut | Rôle |
horizontalSpacing | 5 | préciser l'espace horizontal entre chaque cellule |
makeColumnsEqualWidth | false | donner à toutes les colonnes de la grille la même largeur |
marginHeight | 5 | préciser la hauteur de la marge |
marginWidth | 5 | préciser la largeur de la marge |
numColumns | 1 | préciser le nombre de colonnes de la grille |
verticalSpacing | 5 | préciser l'espace vertical entre cellules |
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
public class TestSWT28 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
shell.setLayout(gridLayout);
Label label1 = new Label(shell, SWT.NONE);
label1.setText("Donnee 1 :");
Text text1 = new Text(shell, SWT.BORDER);
text1.setSize(200, 10);
Label label2 = new Label(shell, SWT.NONE);
label2.setText("Donnee 2 :");
Text text2 = new Text(shell, SWT.BORDER);
text2.setSize(200, 10);
Label label3 = new Label(shell, SWT.NONE);
label3.setText("Donnee 3 :");
Text text3 = new Text(shell, SWT.BORDER);
text3.setSize(200, 10);
Button button1 = new Button(shell, SWT.NONE);
button1.setText("Valider");
Button button2 = new Button(shell, SWT.NONE);
button2.setText("Annuler");
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Les paramètres liés à un composant d'une cellule particulière de la grille peuvent être précisés grâce à un objet de type GridData. Ces paramètres précisent le comportement du composant en cas de redimensionnement.
Il existe deux façons de créer un objet de type GridData :
La méthode setLayoutData() permet d'associer un objet GridData à un composant.
Attention : il ne faut pas appliquer le même objet GridData à plusieurs composants (la méthode setLayoutData() doit recevoir des objets GridData différents.).
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
public class TestSWT28 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
shell.setLayout(gridLayout);
Label label1 = new Label(shell, SWT.NONE);
label1.setText("Donnee 1 :");
Text text1 = new Text(shell, SWT.BORDER);
text1.setSize(200, 10);
Label label2 = new Label(shell, SWT.NONE);
label2.setText("Donnee 2:");
Text text2 = new Text(shell, SWT.BORDER);
text2.setSize(200, 10);
Label label3 = new Label(shell, SWT.NONE);
label3.setText("Donnee 3 :");
Text text3 = new Text(shell, SWT.BORDER);
text3.setSize(200, 10);
Button button1 = new Button(shell, SWT.NONE);
button1.setText("Valider");
Button button2 = new Button(shell, SWT.NONE);
button2.setText("Annuler");
GridData data = new GridData();
data.widthHint = 120;
label1.setLayoutData(data);
data = new GridData();
data.widthHint = 220;
text1.setLayoutData(data);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Ce gestionnaire possède deux propriétés :
Propriété | Valeur par défaut | Rôle |
marginHeight | 0 | préciser la hauteur de la marge |
marginWidth | 0 | préciser la largeur de la marge |
Ce gestionnaire impose d'associer à chaque composant un objet de type FormData qui va préciser les informations de positionnement et de comportement du composant.
La gestion des événements avec SWT est très similaire à celle proposée par l'API Swing car elle repose sur les Listeners. Ces Listeners doivent être ajoutés au contrôle en fonction des événements qu'ils doivent traiter.
Dès lors, lorsque l'événement est émis suite à une action de l'utilisateur, la méthode correspondante du Listener enregistré est exécutée.
Dans la pratique, les Listeners sont des interfaces qu'il faut faire implémenter par une classe selon les besoins. Cette implémentation définira donc des méthodes qui contiennent les traitements à exécuter pour un événement précis. Un ou plusieurs paramètres fournis à ces méthodes permettent d'obtenir des informations plus précises sur l'événement.
Il suffit ensuite d'enregistrer le Listener auprès du contrôle en utilisant la méthode addXXXListener() du contrôle où XXX représente le type du Listener.
Exemple : pour le traitement d'un clic d'un bouton |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT3 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
Button button = new Button(shell, SWT.NONE);
button.setText("Valider");
button.setBounds(1, 1, 100, 25);
button.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent arg0) {
System.out.println("Appui sur le bouton");
}
public void widgetDefaultSelected(SelectionEvent arg0) {
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Comme avec Swing, SWT propose un ensemble de classes de type Adapter qui sont des classes implémentant les interfaces Listener avec des méthodes vides. Pour les utiliser, il suffit de définir une classe fille qui hérite de la classe de type Adapter adéquate et de redéfinir la ou les méthodes utiles.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT4 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
Button button = new Button(shell, SWT.NONE);
button.setText("Valider");
button.setBounds(1, 1, 100, 25);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent arg0) {
System.out.println("Appui sur le bouton");
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
SWT définit plusieurs Listeners :
Cette interface définit deux méthodes keyPressed() et keyReleased() relatives à des événements émis par le clavier, respectivement lors de l'enfoncement d'une touche et la remontée d'une touche du clavier.
Ces deux méthodes possèdent un objet de type KeyEvent qui contient des informations sur l'événement grâce à trois attributs :
character | contient le caractère de la touche concernée |
keyCode | contient le code de la touche concernée SWT défini des valeurs pour des touches particulières, par exemple SWT.ALT, SWT.ARROW_DOWN, SWT_ARROW_LEFT, SWT.CTRL, SWT.CR, SWT.F1, SWT.F2, ... |
stateMask | contient l'état du clavier au moment de l'émission de l'événement, ce qui permet de savoir si l'une des touches Shift, Alt ou Ctrl était enfoncée au moment de l'événement. Il suffit pour cela de comparer la valeur avec SWT.SHIFT, SWT.ALT ou SWT.CTRL. |
SWT définit une classe KeyAdapter qui implémente l'interface KeyListener avec des méthodes vides.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT5 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
shell.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String res = "";
switch (e.character) {
case SWT.CR :
res = "Touche Entree";
break;
case SWT.DEL :
res = "Touche Supp";
break;
case SWT.ESC :
res = "Touche Echap";
break;
default :
res = res + e.character;
}
System.out.println(res);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Exemple : utilisation de la propriété stateMask |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT6 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
shell.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String res = "";
if (e.keyCode == SWT.SHIFT) {
res = "touche shift";
} else {
if ((e.stateMask & SWT.SHIFT) != 0) {
res = "" + e.character + " + touche shift";
}
}
System.out.println(res);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit trois méthodes mouseDown(), mouseUp() et mouseDoubleClick() relatives à des événements émis par un clic sur la souris, respectivement l'enfoncement d'un bouton et le relâchement d'un bouton ou le double clic sur un bouton de la souris.
Ces trois méthodes possèdent un objet de type MouseEvent qui contient des informations sur l'événement grâce à quatre attributs :
button | contient le numéro du bouton utilisé (de 1 à 3). Attention, la valeur est dépendante du système utilisé, par exemple sous Windows avec une souris à molette possédant deux boutons, l'appui sur le bouton de droite renvoie 3 |
stateMask | contient l'état du clavier au moment de l'émission de l'événement, ce qui permet de savoir par exemple si la touche Alt ou Shift ou Ctrl est enfoncée au moment de l'événement en effectuant un test sur la valeur avec SWT.ALT ou SWT.CTRL ou SWT.SHIFT |
x | contient la coordonnée x du pointeur de la souris par rapport au contrôle lors de l'émission de l'événement |
y | contient la coordonnée y du pointeur de la souris par rapport au contrôle lors de l'émission de l'événement |
SWT définit une classe MouseAdapter qui implémente l'interface MouseListener avec des méthodes vides.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT7 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
shell.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
String res = "";
res = "bouton " + e.button + ", x = " + e.x + ", y = " + e.y;
if ((e.stateMask & SWT.SHIFT) != 0) {
res = res + " + touche shift";
}
System.out.println(res);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit une seule méthode mouseMove() relative aux événements émis lors du déplacement de la souris au-dessus d'un contrôle.
Cette méthode possède un objet de type MouseEvent qui contient des informations sur l'événement grâce à quatre attributs.
La mise en oeuvre est similaire de l'interface MouseListener.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT8 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
shell.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent e) {
String res = "";
if ((e.x < 20) & (e.y < 20)) {
res = "x = " + e.x + ", y = " + e.y;
if ((e.stateMask & SWT.SHIFT) != 0) {
res = res + " + touche shift";
}
System.out.println(res);
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit trois méthodes mouseEnter(), mouseExit() et mouseHover() relatives à des événements émis respectivement par l'entrée de la souris sur la zone d'un composant, la sortie et le passage au-dessus de la zone d'un composant.
Ces trois méthodes possèdent un objet de type MouseEvent.
SWT définit une classe MouseTrackAdapter qui implémente l'interface MouseListener avec des méthodes vides.
Exemple : changement de la couleur de fond de la fenêtre |
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
public class TestSWT9 {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
final Color couleur1 = new Color(display,155,130,0);
final Color couleur2 = new Color(display,130,130,130);
shell.setText("Test");
shell.addMouseTrackListener(new MouseTrackAdapter() {
public void mouseEnter(MouseEvent e) {
shell.setBackground(couleur1);
}
public void mouseExit(MouseEvent e) {
shell.setBackground(couleur2);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit une seule méthode modifyText() relative à un événement émis lors de la modification du contenu d'un contrôle de saisie de texte.
Cette méthode possède un objet de type ModifyEvent.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT10 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
Text text = new Text(shell, SWT.BORDER);
text.setText("mon texte");
text.setSize(100, 25);
text.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
System.out.println("nouvelle valeur = " + ((Text)e.widget).getText());
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit une seule méthode verifyText() relative à un événement émis lors de la vérification des données avant modification du contenu d'un contrôle de saisie de texte.
Cette méthode possède un objet de type VerifyEvent qui contient des informations sur l'événement grâce à quatre attributs :
doit | un drapeau qui indique si la modification doit être effectuée ou non |
end | la position de fin de la modification |
start | la position de début de la modification |
text | la valeur de la modification |
Exemple : n'autoriser la saisie que de chiffres |
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
public class TestSWT11 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Test");
Text text = new Text(shell, SWT.BORDER);
text.setText("");
text.setSize(100, 25);
text.addVerifyListener(new VerifyListener() {
public void verifyText(VerifyEvent e) {
int valeur = 0;
e.doit = true;
if (e.text != "") {
try {
valeur = Integer.parseInt(e.text);
} catch (NumberFormatException e1) {
e.doit = false;
}
}
System.out.println(
"start = " + e.start + ", end = " + e.end + ", text = " + e.text);
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit deux méthodes focusGained() et focusLost() relatives à un événement émis respectivement lors de la prise et la perte du focus par un contrôle.
Ces méthodes possèdent un objet de type FocusEvent.
SWT définit une classe FocusAdapter qui implémente l'interface FocusListener avec des méthodes vides.
Exemple : |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.*;
public class TestSWT12 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
Text text = new Text(shell, SWT.BORDER);
text.setText("mon texte");
text.setBounds(10, 10, 100, 25);
text.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
System.out.println(e.widget + " obtient le focus");
}
public void focusLost(FocusEvent e) {
System.out.println(e.widget + " perd le focus");
}
});
Button button = new Button(shell, SWT.NONE);
button.setText("Valider");
button.setBounds(10, 40, 100, 25);
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit une méthode keyTraversed() relative à un événement émis lors de la traversée d'un contrôle au moyen de la touche tab ou des flèches haut et bas.
Cette méthode possède un objet de type TraverseEvent qui contient des informations sur l'événement grâce à deux attributs :
Attribut | Rôle |
doit | un drapeau qui indique si le composant peut être traversé ou non |
detail | le type de l'opération qui génère la traversée |
Exemple : empêcher le parcours des contrôles dans l'ordre inverse par la touche tab |
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.*;
public class TestSWT13 {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
TraverseListener tl = new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
String res = "";
res = e.widget + " est traverse grace à ";
switch (e.detail) {
case SWT.TRAVERSE_TAB_NEXT :
res = res + " l'appui sur la touche tab";
e.doit = true;
break;
case SWT.TRAVERSE_TAB_PREVIOUS :
res = res + " l'appui sur la touche shift + tab";
e.doit = false;
break;
default :
res = res + " un autre moyen";
}
System.out.println(res);
}
};
Text text = new Text(shell, SWT.BORDER);
text.setText("mon texte");
text.setBounds(10, 10, 100, 25);
text.addTraverseListener(tl);
Button button = new Button(shell, SWT.NONE);
button.setText("Valider");
button.setBounds(10, 40, 100, 25);
button.addTraverseListener(tl);
shell.pack();
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
Cette interface définit une méthode paintControl() relative à un événement émis lors de la nécessité de redessiner le composant.
Cette méthode possède un objet de type PaintEvent qui contient des informations sur l'événement grâce à plusieurs attributs :
Attribut | Rôle |
gc | un objet de type GC qui encapsule le contexte graphique |
height | la hauteur de la zone à redessiner |
width | la longueur de la zone à redessiner |
x | l'abscisse de l'origine de la zone à redessiner |
y | l'ordonnée de l'origine de la zone à redessiner |
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
public class TestSWT21 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(420, 420);
Canvas canvas = new Canvas(shell, SWT.NONE);
canvas.setSize(200, 200);
canvas.setLocation(10, 10);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
GC gc = e.gc;
gc.drawText("Bonjour", 20, 20);
gc.drawLine(10, 10, 10, 100);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.drawOval(60, 60, 60, 60);
}
});
shell.pack();
shell.open();
GC gc = new GC(canvas);
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Remarque : il est important d'associer le listener avant d'ouvrir la fenêtre. Il n'est pas utile d'utiliser la méthode dispose() de l'objet de type GC car le code n'est pas responsable de son instanciation.
Comme dans toutes les interfaces graphiques, SWT permet l'utilisation de boîtes de dialogue soit prédéfinies soit personnalisées.
SWT propose plusieurs boîtes de dialogue prédéfinies.
La classe MessageBox permet d'afficher un message à l'utilisateur et éventuellement de sélectionner une action standard via un bouton.
Les styles utilisables avec MessageBox sont :
La méthode setMessage() permet de préciser le message qui va être affiché à l'utilisateur.
La méthode open permet d'ouvrir la boîte de dialogue et de connaître le bouton qui a été utilisé pour fermer la boîte de dialogue en comparant la valeur de retour avec la valeur de style du bouton correspondant.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class TestSWT18 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Afficher");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
int reponse = 0;
MessageBox mb = new MessageBox(shell,
SWT.ICON_INFORMATION | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
mb.setMessage("Message d'information pour l'utilisateur");
reponse = mb.open();
if (reponse == SWT.ABORT) {
System.out.println("Bouton abandonner selectionne");
}
if (reponse == SWT.RETRY) {
System.out.println("Bouton reessayer selectionne");
}
if (reponse == SWT.IGNORE) {
System.out.println("Bouton ignorer selectionne");
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Cette boîte de dialogue permet la sélection d'une couleur dans la palette des couleurs.
La méthode setRGB() permet de préciser la couleur qui est sélectionnée par défaut.
La méthode open() permet d'ouvrir la boîte de dialogue et de renvoyer la valeur de la couleur sélectionnée sous la forme d'un objet de type RGB. Si aucune couleur n'est sélectionnée (appui sur le bouton annuler dans la boîte de dialogue) alors l'objet renvoyé est null.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.graphics.*;
public class TestSWT15 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Couleur");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
Color couleurDeFond = shell.getBackground();
ColorDialog colorDialog = new ColorDialog(shell);
colorDialog.setRGB(couleurDeFond.getRGB());
RGB couleur = colorDialog.open();
if (couleur != null) {
if (couleurDeFond != null)
couleurDeFond.dispose();
couleurDeFond = new Color(display, couleur);
shell.setBackground(couleurDeFond);
}
}
});
shell.getBackground().dispose();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Cette classe encapsule une boîte de dialogue permettant la sélection d'une police de caractère.
La méthode open() permet d'ouvrir la boîte de dialogue et renvoie un objet de type FontData qui encapsule les données de la police sélectionnée ou renvoie null si aucune n'a été sélectionnée.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
public class TestSWT19 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Label lblNomPolice = new Label(shell, SWT.NONE);
lblNomPolice.setText("Nom de la police = ");
final Text txtNomPolice = new Text(shell, SWT.BORDER | SWT.READ_ONLY);
txtNomPolice.setText("");
txtNomPolice.setSize(280, 40);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Police");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
FontDialog dialog = new FontDialog(shell, SWT.OPEN);
FontData fontData = dialog.open();
if (fontData != null) {
txtNomPolice.setText(fontData.getName());
System.out.println("selection de la police " + fontData.getName());
if (txtNomPolice.getFont() != null) {
txtNomPolice.getFont().dispose();
}
Font font = new Font(display, fontData);
txtNomPolice.setFont(font);
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Cette boîte de dialogue permet de sélectionner un fichier.
La méthode open() ouvre la boîte de dialogue et renvoie le nom du fichier sélectionné. Si aucun fichier n'est sélectionné, alors elle renvoie null.
La méthode setFilterExtensions() permet de préciser sous la forme d'un tableau de chaînes la liste des extensions de fichiers acceptées par la sélection.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class TestSWT16 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Label lblNomFichier = new Label(shell, SWT.NONE);
lblNomFichier.setText("Nom du fichier = ");
final Text txtNomFichier = new Text(shell, SWT.BORDER | SWT.READ_ONLY);
txtNomFichier.setText("");
txtNomFichier.setSize(280,40);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Ouvrir");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
String nomFichier;
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setFilterExtensions(new String[] { "*.java", "*.*" });
nomFichier = dialog.open();
if ((nomFichier != null) && (nomFichier.length() != 0)){
txtNomFichier.setText(nomFichier);
System.out.println("selection du fichier "+nomFichier);
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Cette classe encapsule une boîte de dialogue qui permet la sélection d'un répertoire.
La méthode open() ouvre la boîte de dialogue et renvoie le nom du répertoire sélectionné. Si aucun répertoire n'est sélectionné, alors elle renvoie null.
La méthode setFilterPath() permet de préciser sous la forme d'une chaîne de caractères le répertoire sélectionné par défaut.
La méthode setMessage() permet de préciser un message qui sera affiché dans la boîte de dialogue.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class TestSWT17 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Label lblNomFichier = new Label(shell, SWT.NONE);
lblNomFichier.setText("Nom du fichier = ");
final Text txtNomRepertoire = new Text(shell, SWT.BORDER | SWT.READ_ONLY);
txtNomRepertoire.setText("");
txtNomRepertoire.setSize(280,40);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Ouvrir");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
String nomRepertoire;
DirectoryDialog dialog = new DirectoryDialog(shell, SWT.OPEN);
dialog.setFilterPath("d:/");
dialog.setMessage("Test");
nomRepertoire = dialog.open();
if ((nomRepertoire != null) && (nomRepertoire.length() != 0)){
txtNomRepertoire.setText(nomRepertoire);
System.out.println("selection du repertoire "+nomRepertoire);
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
La classe PrintDialog encapsule une boîte de dialogue permettant la sélection d'une imprimante configurée sur le système. Pour utiliser cette classe, il faut importer la package org.eclipse.swt.printing.
La méthode open() permet d'ouvrir la boîte de dialogue et renvoie un objet de type PrinterData qui encapsule les données de l'imprimante sélectionnée ou renvoie null si aucune n'a été sélectionnée.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.printing.*;
import org.eclipse.swt.graphics.*;
public class TestSWT20 {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300, 300);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Imprimer");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
PrintDialog dialog = new PrintDialog(shell, SWT.OPEN);
PrinterData printerData = dialog.open();
if (printerData != null) {
Printer printer = new Printer(printerData);
if (printer.startJob("Test")) {
printer.startPage();
GC gc = new GC(printer);
gc.drawString("Bonjour", 100, 100);
printer.endPage();
printer.endJob();
gc.dispose();
printer.dispose();
}
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Remarque : cet exemple est très basic dans la mesure où il est préférable de lancer les tâches d'impression dans un thread pour ne pas bloquer l'interface utilisateur pendant ces traitements.
Pour définir une fenêtre qui sera une boîte de dialogue, il suffit de définir un nouvel objet de type Shell qui sera lui-même rattaché à sa fenêtre mère.
Exemple : |
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class TestSWT14 {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setSize(300,300);
Button btnOuvrir = new Button(shell, SWT.PUSH);
btnOuvrir.setText("Ouvrir");
btnOuvrir.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
final Shell fenetreFille = new Shell(shell, SWT.TITLE | SWT.CLOSE);
fenetreFille.setText("Boite de dialogue");
fenetreFille.setLayout(new GridLayout());
fenetreFille.addListener(SWT.Close, new Listener() {
public void handleEvent(Event e) {
System.out.println("Fermeture de la boite de dialogue");
}
});
Button btnFermer = new Button(fenetreFille, SWT.PUSH);
btnFermer.setText("Fermer");
btnFermer.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
fenetreFille.close();
}
});
fenetreFille.setSize(200, 200);
fenetreFille.open();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}