Drag & Drop avec Style et l'API Swing

Romain Guy

Drag n' Ghost : démonstration de Drag & Drop avec l'API Swing. ♪

- Titre : Drag & Drop avec Style et l'API Swing

- Auteur : Romain Guy

- Parution : 10 juin 2006

- Mise à jour : 3 avril 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Romain Guy. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Démonstration avec Java Web Start

- II. Explications

- III. Téléchargements

I - Démonstration avec Java Web Start

Prérequis : pour essayer cette démonstration, vous devez disposer de Java Web Start (compris avec le JRE et le JDK).

Lancez la démonstration

II - Explications

Une manière très sympa de créer des interfaces graphiques user friendly est de permettre de faire du drag & drop de tout ce que l'on veut dans, depuis et à l'intérieur même de l'application. MacOS X est l'exemple parfait d'une bonne utilisation de drag & drop. À chaque fois que j'ai essayé de dragger quelque chose et de le dropper dans quelque chose d'autre, ça a marché. Sauf bien sûr si vous essayez de faire quelque chose de stupide du style dropper un fichier texte sur l'icône d'un jeu. Bien sûr Windows et Linux permettent aux applications d'implémenter du drag & drop, mais il leur manque quelque chose que MacOS X offre déjà : des effets visuels vraiment cools. Par exemple, dragger une image depuis Safari, le navigateur web, vous laisse voir une jolie vignette translucide de l'objet.

Comment pouvons-nous nous débarrasser des curseurs de drag & drop simplistes offerts par Java ? La solution réside dans la démo Drag n' Ghost que je vais vous montrer. Voyez par vous-même, vous n'aimez pas cette jolie image translucide ?

Dragger une image c'est bien, mais ce ne serait pas mieux de pouvoir dragger n'importe quel composant tout en gardant ce bel effet ? Aucun problème :

Toujours pas convaincu ? Voyons à quoi ça ressemble de dragger toute une JTable :

Maintenant que j'ai votre attention, voyons voir comment utiliser ça dans vos applications. L'astuce est d'utiliser un glass pane pour dessiner l'image translucide des composants par-dessus l'UI. Vous devez donc mettre un GhostGlassPane à la fenêtre et attacher un GhostDropAdapter et un GhostMotionAdapter au composant que vous voulez dragger :

GhostGlassPane glassPane = new GhostGlassPane();
setGlassPane(glassPane);
JLabel label = new JLabel("Component adapted");
label.addMouseListener(new GhostComponentAdapter(glassPane, "action_1"));
label.addMouseMotionListener(new GhostMotionAdapter(glassPane));
JButton button = new JButton("Picture adapted");
label.addMouseListener(new GhostPictureAdapter(glassPane, "action_2", "image.png"));
label.addMouseMotionListener(new GhostMotionAdapter(glassPane));

Et voilà, c'est aussi simple que ça. Vous pouvez noter que nous n'utilisons pas GhostDropAdapter, mais ses deux sous-classes GhostComponentAdapter et GhostPictureAdapter. La première crée l'image fantôme en dessinant le composant source dans une image offscreen alors que la seconde utilise l'image fantôme que vous lui fournissez.

Chaque GhostDropAdapter peut enregistrer des GhostDropListeners qui sont invoqués lors du drop. L'évènement est une instance de GhostDropEvent qui vous donne le nom de l'action et la localisation du drop. Tant que cette position est dans les coordonnées de l'écran, il est conseillé d'utiliser AbstractGhostDropManager qui propose deux méthodes intéressantes.

Un tel manager est attaché à un composant (voir le constructeur) appelé la cible. Deux méthodes vous permettent de gérer le composant : isInTarget() vérifie si la position du drop est à l'intérieur des bornes du composant cible et getTranslatedPoint() traduit les coordonnées écran dans le système de coordonnées de la cible. GhostDropManagerDemo vous montre comment créer un manager personnalisé. Dans cet exemple, le manager attend un drop sur la JTable et montre le nom de l'action :

Cependant, l'ensemble des composants GhostDrop souffrent de deux problèmes. Tout d'abord, les performances peuvent être très mauvaises quand vous draggez un ghost sur une grande fenêtre. Je ne l'ai vu se produire que sur mon ordinateur, mais je ne doute pas que cela peut se produire aussi sur les vôtres. Je ne vois pas comment optimiser le rendu à part peut-être utiliser une VolatileImage (et je ne suis pas certain du résultat). Le second problème se produit quand le focus est donné à une autre fenêtre alors que vous êtes en train de dragger quelque chose. Je pense que cela peut être résolu très facilement en écoutant le focus de la fenêtre parent.

III - Téléchargements

Code source