:: Présentation de SWT/JFace :: Principes d'utilisation
avec JFace ::
SWT procure des composants natifs à l'état "
brut ". Les objets qu'ils utilisent sont uniquement liés
à l'aspect graphique du composant, comme par exemple
des chaînes de caractères (String) ou des images
(Image).
De ce fait leur utilisation n'est pas aisée. Dans les
développements MVC, il va systématiquement falloir
convertir manuellement l'objet modèle métier en
objets utilisés par le composant de la vue (String,
).
Pour cela, des mécanismes génériques d'utilisation
de SWT ont été regroupés dans une surcouche
" outil " de SWT : JFace. La vocation de JFace est
de simplifier les développements en SWT, sans pour autant
masquer totalement SWT. Comme on peut le voir ici, la plateforme
eclipse utilise conjointement SWT et JFace.
:: Utilisation des Viewers ::
Dans cette optique, les viewers JFace permettent d'utiliser
les composants graphiques SWT avec des objets métier.
On peut les voir comme des adaptateurs sur les widgets SWT.
Il existe des Viewers pour tous les widgets SWT non triviaux,
comme la liste (List), l'arbre (Tree), la table (Table)
Le nom de leur classe est d'ailleurs composé du nom du
widget SWT suivi de " Viewer " : ListViewer, TreeViewer,
TableViewer
Ainsi, chaque viewer est directement associé à
un composant SWT.
Le fonctionnement des Viewers s'articule autour de 3 notions
principales :
- Input
L'input est l'objet principal qu'affiche le viewer. Il 'agit
de n'importe quel objet (en principe un objet métier),
simple ou composé. Il est spécifié par
la méthode setInput(Object)
du viewer. L'objet input peut être changé dynamiquement
au cours de la vie du viewer et peut être null
si le viewer ne doit rien afficher.
- ContentProvider
Le ContentProvider a pour but d'extraire des informations de l'objet
input. Concrètement, il s'agit d'une interface adaptée
au type du viewer. Par exemple : l'interface StructuredContentProvider
procure une liste d'objets pour un input donné avec une
méthode getElements(). Il est
utilisé par les viewers de type " liste ".
Accessoirement, le ContentProvider est informé du changement
d'input.
Lorsqu'on utilise un viewer JFace, il est donc nécessaire
d'écrire sa propre implémentation de ContentProvider
et de la fournir au viewer à l'aide de la méthode
setContentProvider(IContentProvider)
- LabelProvider
Le LabelProvider produit, pour chaque élément
obtenu à partir du ContentProvider, des éléments
graphiques spécifiques au contenu du viewer (chaine de
caractères, image) par le biais d'une interface adaptée.
Il faut dournir son implémentation de LabelProvider au
viewer à l'aide de la méthode setLabelProvider(ILabelProvider).
L'article "Using
the Eclipse GUI outside the Eclipse Workbench, Part 1: Using
JFace and SWT in stand-alone mode" présente
un bon exemple d'introduction aux viewers jface.
Le schéma suivant montre un exemple d'utilisation du
TreeViewer pour afficher une arborescence de fichiers. L'objet
input du viewer est un fichier qui sera la racine de l'arborescence.
Sur ce fichier input, l'implémentation de la méthode
getElements() du ContentProvider retourne
les fichiers enfants du fichier input à l'aide de la
méthode listFiles(). Sur chacun
des éléments retournés par la méthode
getElements() du ContentProvider,
le LabelProvider détermine le texte correspondant à
afficher dans l'arbre. Ici, l'implémentation du LabelProvider
affiche le nom du fichier en appelant la méthode getName()
sur les éléments.
:: Autres atouts de SWT/JFace ::
En plus de permettre la manipulation d'objets métiers,
les viewers JFace implémentent certains mécanismes
assez pratiques. Les viewers de type " liste " offrent
par exemple des possibilités de tri et de filtres personnalisés
par l'intermédiaire des classes abstraites respectives
ViewerSorter et ViewerFilter. Ainsi il est possible de spécifier
un " trieur " à l'aide de la méthode
setSorter(ViewerSorter) et d'ajouter
plusieurs filtres à l'aide de la méthode
addFilter(ViewerFilter). Enfin, il
existe une grande variété de composants SWT/JFace
(viewers ou non). On notera par exemple la disponibilité
d'un assistant pas à pas (wizard) configurable (org.eclipse.jface.wizard),
une première!
En guise de second exemple, le composant FilterdList procure
une liste d'élément filtrable par une chaîne
de caractère saisie dans une zone de texte et supportant
les caractères spéciaux (*,?).Enfin eclipse étant
lui-même open source, tout ce qui a été
développé dans eclipse est à priori réutilisable
ou peut servir d'exemple d'utilisation de SWT/JFace.
:: Appels SWT dans des Threads ::
Il arrive souvent qu'un Thread ait besoin de manipuler l'interface
graphique. Ceci ne peut se faire directement en SWT sous peine
d'obtenir une exception: "org.eclipse.swt.SWTException:
Invalid thread access". Une question
des FAQ en explique clairement la raison.
Voici la méthode à suivre pour résoudre
ce problème. Lorsque qu'un Thread a besoin de faire des
choses graphiques avec SWT, il faut mettre les appels graphiques
dans un Runnable et lancer le Runnable
avec parent.getDisplay().syncExec(le_runnable)
ou parent.getDisplay().asyncExec(le_runnable).
Typiquement, étant donné que le runnable utilisé
pour faire les appels graphique est tout petit, inutile de créer
une nouvelle classe dans le package ni même de créer
une classe interne. Il suffit de créer une classe anonyme
au coeur de la méthode run()
(ou autre).
La nuance entre syncExec et asyncExec
est la suivante: avec syncExec, le
run de le Thread sera bloqué
jusqu'à la fin du run faisant
appel à l'interface graphique. Exemple d'utilisation
de syncExec: message bloquant à
l'utilisateur.
Avec asyncExec, le run du Thread continuera
à s'exécuter en parallèle du run
utilisant l'interface graphique. Exemple d'utilisation: barre
de progression.
Voici un exemple de Thread faisant des appels à SWT (ici,
affichage d'un message d'erreur):
class MyThread implements Runnable{
private Composite parent;
public MyThread(Composite parent){
this.parent=parent;
}
public void run(){
// traitement
// ...
// affichage d'un message d'erreur à
l'utilisateur
parent.getDisplay().syncExec(new Runnable(){
public void run(){
showErrorMessage("Erreur
de copie de fichier", "Le fichier est introuvable");
}
});
}
private void showErrorMessage(String title, String
message) {
MessageDialog d =
new MessageDialog(
parent.getShell(),
title,
null,
message,
MessageDialog.ERROR,
new String[] { "Ok"
},
0);
d.open();
}
}
:: Pré-requis ::
Pour développer une application SWT/JFace en standalone,
il est nécessaire d'avoir un certain nombre de jars dans
le classpath. Ces jars sont fournis avec eclipse et se trouvent
dans les répertoires suivants ($ECLIPSE_HOME est votre
chemin d'installation d'eclipse, et XXX est la version utilisée):
- $ECLIPSE_HOME/plugins/org.eclipse.core.boot_XXX/boot.jar
- $ECLIPSE_HOME/plugins/org.eclipse.runtime_XXX/runtime.jar
- $ECLIPSE_HOME/plugins/org.eclipse.ui.workbench_XXX/workbench.jar
- $ECLIPSE_HOME/plugins/org.eclipse.core.runtime_XXX/runtime.jar
- $ECLIPSE_HOME/plugins/org.eclipse.jface_XXX/jface.jar
Il faut également le swt.jar correspondant à
la plateforme utilisée :
Windows :
- $ECLIPSE_HOME/plugins/org.eclipse.swt.win32_XXX/ws/win32/swt.jar
GTK:
- $ECLIPSE_HOME/plugins/org.eclipse.swt.gtk_XXX/ws/gtk/swt.jar
Motif:
- $ECLIPSE_HOME/plugins/org.eclipse.swt.motif_XXX/ws/motif/swt.jar
MacOS:
- $ECLIPSE_HOME/plugins/org.eclipse.swt.carbon_XXX/ws/carbon/swt.jar
Photon:
- $ECLIPSE_HOME/plugins/org.eclipse.swt.photon_XXX/ws/photon/swt.jar
En fonction de la plateforme et de la version, il se peut qu'il
y ait plusieurs jars à récupérer pour swt
(dans le même répertoire de swt.jar). Par exemple,
en GTK et dans la version 2.1.1, il faut également swt-pi.jar.
Enfin, il faut spécifier à la JVM l'emplacement
des bibliothèques natives SWT, toujours en fonction de
la plateforme utilisée. Pour cela, il faut ajouter l'argument
" -Djava.library.path= " suivi du chemin adapté
à la plateforme :
- win32: $ECLIPSE_HOME\plugins\org.eclipse.swt.win32_XXX\os\win32\x86
- linux gtk: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.gtk_XXX/os/linux/x86
- linux motif: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.motif_XXX/os/linux/x86
- solaris motif: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.motif_XXX/os/solaris/sparc
- aix motif: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.motif_XXX/os/aix/ppc
- hpux motif: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.motif_XXX/os/hpux/PA_RISC
- photon qnx: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.photon_XXX/os/qnx/x86
- macosx: $ECLIPSE_HOME/eclipse/plugins/org.eclipse.swt.carbon_XXX/os/macosx/ppc
:: Où trouver la javadoc ? ::
La javadoc de SWT/JFace se trouve dans le répertoire
$ECLIPSE_HOME/plugins/org.eclipse.platform.doc.isv_XXX/doc.zip.
Elle est également consultable en ligne ICI.
|