:: Accueil :: Présentation de SWT/JFace :: Comparatif SWT/Swing :: Téléchargements :: Liens :: Contacts ::

:: Présentation de SWT/JFace :: Principes d'utilisation avec JFace ::

:: Présentation de 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.

couches swt, jface et eclipse


:: 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.

exemple d'utilisation d'un tableviewer

:: 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.


 
(c) 2004 Nicolas SEBBAN