Parfois, vous pouvez trouver qu'aucun des contrôles fournis dans SWT ne répond aux besoins de votre application. Dans ce cas, vous pouvez étendre SWT en implémentant votre propre widget personnalisé. SWT fournit lui-même un package, org.eclipse.swt.custom, qui contient des contrôles personnalisés ne figurant pas dans le groupe principal de contrôles SWT, mais qui sont nécessaires pour implémenter le plan de travail de la plateforme.
Contrôle
|
Objectif
|
Styles
|
Evénements |
---|---|---|---|
Similaire à Combo, mais personnalisé pour permettre l'utilisation d'une boîte de dialogue mixte sans bordure. Cette classe a été développée pour pouvoir utiliser des boîtes de dialogue mixtes dans les cellules de tableau. |
BORDER, FLAT, READ_ONLY |
Dispose, Control*, Selection | |
Similaire à Label, mais supporte la troncature de texte avec ellipses. Supporte également un effet dégradé de la couleur d'arrière-plan, comme on peut le voir dans la vue du plan de travail actif. Ne supporte pas les retours à la ligne. |
CENTER, LEFT, RIGHT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE |
Dispose, Control* | |
Similaire à TabFolder, mais supporte une configuration supplémentaire de l'apparence visuelle des onglets (supérieurs ou inférieurs) et des bordures. |
BORDER, FLAT, BOTTOM, TOP |
Dispose, Control*, Selection | |
Objet de l'interface utilisateur sélectionnable, correspondant à un onglet pour une page dans un CTabFolder. |
|
Dispose, Control* | |
Contrôle composite présentant ses enfants en ligne ou en colonne et utilisant un bouton de réglage pour les séparer de telle sorte que l'utilisateur puisse les redimensionner. |
BORDER, HORIZONTAL, VERTICAL |
Dispose, Control* | |
Contrôle composite faisant défiler son contenu et qui éventuellement l'étend pour remplir l'espace disponible. |
BORDER, H_SCROLL, V_SCROLL |
Dispose, Control* | |
Contrôle éditable permettant à l'utilisateur de saisir du texte. Les plages de texte à l'intérieur du contrôle peuvent avoir une police et une couleur distinctes (avant-plan et arrière-plan). |
BORDER, FULL_SELECTION, MULTI, SINGLE, WRAP, READ_ONLY |
Dispose, Control*, ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey | |
Contrôle sélectionnable qui affiche une liste hiérarchique d'éléments pouvant être sélectionnés par l'utilisateur. Les éléments sont présentés en lignes qui affichent plusieurs colonnes représentant différents aspects des éléments. |
BORDER, SINGLE, MULTI, CHECK, FULL_SELECTION |
Dispose, Control*, Selection, DefaultSelection, Collapse, Expand | |
Objet de l'interface utilisateur sélectionnable représentant une hiérarchie d'éléments dans une TableTree. |
|
||
Contrôle composite qui présente trois enfants horizontalement et permet un contrôle programmatique des paramètres de présentation et des bordures. Utilisé dans le plan de travail pour implémenter la barre locale libellé/barre d'outils/menu d'une vue. |
BORDER, FLAT |
Dispose, Control* |
Contrôle* = événements hérités du contrôle : FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter, MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize
Avant d'implémenter un widget personnalisé, vous devez considérer plusieurs points importants :
Dès lors que vous avez déterminé qu'un widget personnalisé est nécessaire et décidé quelles plateformes doivent être supportées, vous pouvez envisager plusieurs techniques d'implémentation pour votre widget. Ces techniques peuvent être mélangées et appariées en fonction de ce qui est disponible sur la plateforme du système d'exploitation sous-jacent.
Si votre application requiert un widget natif qui n'est pas fourni par SWT, vous devez également l'implémenter de manière native. Il peut s'agir d'un widget de plateforme, d'un widget tiers ou de tout autre widget de la bibliothèque partagée d'une plateforme.
Chaque plateforme SWT est livrée avec une bibliothèque partagée (par exemple une DLL sous Windows) et un JAR (pour les fichiers classe Java). La bibliothèque partagée contient la totalité de la fonction native requise pour SWT, mais cela ne signifie pas qu'il s'agisse du jeu complet de fonctions disponibles sur la plateforme. Pour exposer la fonction native ou des widgets natifs n'ayant pas été exposé par SWT, vous devez écrire votre propre bibliothèque partagée. Si vous utilisez une combinaison de code natif sur une plateforme et un code transférable sur une autre, veillez à appeler votre bibliothèque partagée sur la plateforme avec le widget natif, et votre fichier jar sur la plateforme avec le widget transférable.
Pour implémenter un widget natif, vous devez comprendre l'interface JNI (Java Native Interface), l'API du widget dans la bibliothèque partagée et les API de la plateforme du système d'exploitation sous-jacent en langage C.
Le processus de base d'implémentation est de décider quelle partie de l'API du widget natif sera exposée dans l'API Java et d'écrire le code Java qui appelle les natifs à implémenter le comportement. Un code C JNI peut être écrit pour appeler la bibliothèque partagée.
C'est une bonne idée de suivre les principes de conception utilisés pour implémenter SWT lors de la génération de votre propre implémentation de widgets natifs. Par exemple, vos natifs JNI doivent mapper un à un les appels d'API réalisés dans la bibliothèque partagée.
Un exemple complet d'implémentation de widget personnalisé natif figure à l'article Creating Your Own Widgets using SWT.
Si le concept ou l'implémentation de votre nouveau widget est similaire à un widget existant, vous pouvez encapsuler un widget SWT existant. Cette technique est utilisée pour l'implémentation de TableTree.
Pour encapsuler un widget, vous devez créer une sous-classe du widget Composite ou Canvas (selon que votre contrôle aura ou non des enfants). Dans le constructeur du widget personnalisé, créez le widget encapsulé. Le widget résultant sera du code Java transférable à 100% du fait que vous appelez l'API du widget encapsulé pour votre implémentation.
L'encapsulation d'un widget est souvent une façon plus simple d'implémenter des widgets personnalisés que de démarrer à partir de rien. Cependant, vous devez faire attention lors de la conception de l'API de votre nouveau widget. Voici quelques conseils importants :
Posez-vous la question à savoir si votre widget est une "sorte de" widget encapsulé ou s'il en utilise uniquement un pour son implémentation. Par exemple, une arborescence de tableaux n'est pas une sorte de tableau. Elle ne fait pas référence aux éléments par index de numéro de ligne. TableTree utilise un tableau juste pour implémenter la présentation et ajouter un comportement d'arborescence. Si vous encapsulez un widget simplement pour des raisons d'implémentation, votre API peut être alors différente de celle du widget sous-jacent.
Envoyez aussi peu de méthodes et d'événements que possible. Ne réimplémentez pas l'API complète du widget encapsulé ou bien vous devrez rattraper les changements de l'API dans une version future. Les méthodes communes à la plupart des widgets, telles que setFont, setForeground, setBackground doivent être envoyées.
Si vous vous retrouvez à implémenter la plupart des API du widget encapsulé, envisagez de l'exposer au niveau des API et de laisser le code d'application l'utiliser directement. Dans ce cas, vous pouvez reconsidérer le sens de la génération d'un nouveau widget. Il peut être préférable d'implémenter votre fonction en tant qu'"adaptateur"qui ajoute un comportement au widget, mais ne prétend pas en être un. (Les afficheurs JFace suivent ce schéma.)
Remarque : Cette discussion a mis l'accent uniquement sur l'extension du comportement d'un widget en l'encapsulant. L'extension d'un widget en le sous-classant est fortement déconseillée, car ceci le rendra dépendant de l'implémentation de la super-classe.
Dans certains cas, vous ne disposez pas de code natif, ni de widgets existants qui vous aident à implémenter votre nouveau widget. Ceci signifie que vous devez tracer le widget vous-même à l'aide d'appels graphiques SWT. Bien que cette technique puisse devenir assez compliquée, elle présente l'avantage de fournir une implémentation totalement transférable.
Les contrôles personnalisés sont implémentés en sous-classant la classe Canvas ou Composite selon les règles suivantes :
Dans un contrôle personnalisé, votre état interne est conservé dans des variables d'instance Java. Vous définissez votre API et vos styles en fonction des besoins de votre widget.
L'implémentation interne d'un widget personnalisé implique généralement les tâches principales suivantes :
Un grand nombre des widgets implémentés dans org.eclipse.swt.custom utilisent cette approche. Un simple exemple figure dans CLabel.
Pour plus d'informations sur les widgets personnalisés, reportez-vous à la section Creating your own widgets using SWT.