Lors de l'utilisation d'un toolkit de widget, il est important de comprendre le modèle de traitement sous-jacent utilisé pour la lecture et la distribution des événements de l'interface utilisateur de la plateforme. L'implémentation de l'unité d'exécution de l'interface utilisateur affecte les règles que les applications doivent suivre lors de l'utilisation d'unités d'exécution Java dans leur code.
Sous toute application de l'interface graphique, quel que soit le langage ou le toolkit utilisé, la plateforme du système d'exploitation détecte les événements de l'interface graphique et les place dans les files d'événements de l'application. Bien que les mécanismes soient légèrement différents sur les plateformes d'un système d'exploitation à l'autre, les bases sont similaires. Lorsque l'utilisateur clique à l'aide d'un bouton de la souris, saisit des caractères ou trace des fenêtres, le système d'exploitation génère des événements de l'interface graphique d'application, tels que des clics de souris, des séquences de touches ou des événements de traçage de fenêtre. Cela détermine quelle fenêtre et application doivent recevoir chaque événement et le place dans la file d'événements de l'application.
La structure sous-jacente de toute application de l'interface graphique fenêtrée est une boucle d'événements. Les applications initialisent, puis démarrent une boucle qui lit tout simplement les événements de l'interface graphique dans la file et réagit en fonction. Tout travail effectué pendant le traitement de l'un de ces événements doit avoir lieu rapidement afin que le système de l'interface graphique puisse répondre à l'utilisateur.
Les opérations longues déclenchées par les événements de l'interface graphique doivent être effectuées dans une unité d'exécution distincte afin de permettre à l'unité d'exécution de la boucle d'événements de renvoyer rapidement les données et d'extraire l'événement suivant de la file de l'application. Cependant, l'accès à l'API de la plateforme et des widgets à partir d'autres unités d'exécution doit être contrôlé par un verrouillage et une sérialisation explicites. Une application qui ne parvient pas à suivre les règles peut entraîner l'échec d'un appel du système d'exploitation, ou pire encore, le verrouillage de tout le système de l'interface graphique.
Les programmeurs d'interfaces graphiques natives utilisant le langage C connaissent les questions de conception liées à l'utilisation de la boucle d'événements d'une plateforme. Cependant, des toolkits de widgets de niveau supérieur en langage Java tentent souvent d'épargner les développeurs d'applications de problèmes liés au traitement de l'interface utilisateur en masquant la boucle d'événements de la plateforme.
Un moyen courant pour y parvenir est de configurer une unité d'exécution de l'interface utilisateur avec toolkit dédié pour la lecture et la distribution à partir de la boucle d'événements, et la publication des événements sur une file interne, traitée par des applications s'exécutant en unités d'exécution séparées. Ceci permet au toolkit de répondre en un temps suffisant au système d'exploitation, tout en n'appliquant pas de restriction sur le délai de traitement de l'événement par l'application. Les applications doivent encore utiliser des techniques de verrouillage spéciales pour accéder au code de l'interface utilisateur à partir de leur unité d'exécution d'application, mais ceci est réalisé de manière cohérente tout au long du code du fait que la totalité du code d'application s'exécute dans une unité d'exécution hors interface utilisateur.
Bien qu'il paraisse tentant de "protéger" les applications contre les problèmes liés à l'utilisation d'unités d'exécution de l'interface utilisateur, ceci peut dans la pratique,entraîner de nombreux problèmes.
Il devient difficile de déboguer et de diagnostiquer les problèmes lorsque le délai des événements de l'interface graphique dépend de l'implémentation de l'utilisation d'unités d'exécution Java et des performances de l'application.
Les plateformes des interfaces graphiques modernes réalisent de nombreuses optimisations avec la file d'événements. Une optimisation courante consiste à réduire dans la file les événements de traçage à la suite. Chaque fois qu'un fragment de fenêtre doit être retracé, la file peut être vérifiée pour trouver les événements de traçage qui se chevauchent ou sont redondants et n'ont pas encore été distribués. Ces événements peuvent être fusionnés dans un seul événement de traçage, réduisant ainsi le scintillement et entraînant une exécution moins fréquente du code de traçage de l'application. Cette optimisation échoue si le toolkit de widgets extrait rapidement les événements de la file et les publient sur une file interne.
Changer la perception des développeurs quant eu modèle d'utilisation d'unités d'exécution sème la confusion chez les programmeurs ayant une expérience de programmation du système de l'interface graphique natif dans d'autres langages et toolkits.
SWT suit le modèle d'utilisation d'unité d'exécution supporté directement par les plateformes. Le programme d'application exécute la boucle d'événements dans son unité d'exécution principale et distribue les événements directement à partir de cette unité d'exécution. Il s'agit de l'"unité d'exécution de l'interface utilisateur" de l'application.
Remarque : Techniquement, l'unité d'exécution de l'interface utilisateur est celle qui crée l'affichage. En pratique, il s'agit également de l'unité d'exécution qui exécute la boucle d'événements et crée les widgets.
La totalité du code d'événement étant déclenchée à partir de l'unité d'exécution de l'interface utilisateur de l'application, le code d'application traitant les événements peut librement accéder aux widgets et effectuer des appels graphiques sans aucune technique spéciale. Cependant, l'application est responsable du processus parallèle des unités d'exécution de calcul lors d'opérations longues répondant à un événement.
Remarque : SWT déclenche une exception SWTException pour tous les appels effectués à partir d'une unité d'exécution de l'interface utilisateur.
L'unité d'exécution principale, dont la boucle d'événements, d'une application SWT ressemble à ce qui suit :
public static void main(String[] args) { Display display = new Display (); Shell shell = new Shell (display); shell.open (); // lance la boucle d'événements. Arrêt lorsque l'utilisateur // a agi pour quitter la fenêtre. while (!shell.isDisposed ()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose (); }
Une fois les widgets créés et le shell ouvert, l'application lit et distribue les événements de la file du système d'exploitation jusqu'à ce que la fenêtre shell soit disposée. Si aucun événement n'est disponible pour nous dans la file, nous ordonnons à l'affichage de passer en veille afin que d'autres applications puissent s'exécuter.
Remarque : Le modèle d'utilisation d'unités d'exécution le plus courant pour une application SWT est d'exécuter une seule unité d'exécution de l'interface utilisateur et d'effectuer de longues opérations dans des unités d'exécution de calculs. Cependant, SWT ne limite pas les développeurs à ce modèle. Une application peut exécuter plusieurs unités d'exécution de l'interface utilisateur, avec une boucle d'événements dans chaque unité d'exécution.
SWT fournit des méthodes d'accès spéciales pour appeler le code des graphiques et des widgets à partir d'une unité d'exécution d'arrière-plan.
Les applications souhaitant appeler un code de l'interface utilisateur à partir d'une unité d'exécution sans interface utilisateur doivent fournit un exécutable qui appelle le code de l'interface utilisateur. Les méthodes syncExec(Runnable) et asyncExec(Runnable) de la classe Display sont utilisées pour exécuter ces exécutables dans l'unité d'exécution de l'interface utilisateur à un moment approprié.
Le fragment de code ci-après illustre le schéma d'utilisation de ces méthodes :
// effectue des calculs intensifs ... // met à jour l'interface graphique. ne dépend pas du résultat, // d'où l'utilisation d'async. Display.getDefault ().asyncExec (new Runnable () { public void run() { myWindow.redraw(); } }); // calculs terminés ...
Les règles d'utilisation d'unités d'exécution sont très claires lorsque vous implémentez une application SWT dès son fondement, car vous contrôlez la création de la boucle d'événements et la décision de séparer les unités d'exécution de calculs en processus parallèles dans votre application.
Si vous fournissez du code de plug-in, il n'y a pas de "magie" cachée dans le code du plan de travail ou JFace. Les règles sont simples :