Blogeek|Sioc

Geekeries de tout poil

Fermer les menu en Swing

Petite astuce rapide : comment, depuis le code, fermer les popups de menus ouverts par un utilisateur dans une IHM Swing, comme s’il avait cliqué en dehors des popups ?

Solution rapide :

MenuSelectionManager.defaultManager().clearSelectedPath();

Explications :

On pourrait être tenté d’utiliser un JMenu.setPopupMenuVisible(false) ou ce genre de chose, or cela ne fonctionne pas « bien » : en effet, il suffit de survoler à nouveau un bouton qui déclenche un menu, et celui-ci va poper sans clic. Pourquoi ? Je n’ai pas de réponse d’autorité, mais ce que je soupçonne, c’est que Swing gère l’état des menus, de l’ouverture à la fermeture, avec un Manager, et tant qu’on a pas cliqué en dehors de la popup d’un menu, ou sur un de ses éléments, le Manager considère qu’on est toujours en mode « menu ouvert », ce qui explique la réaction au survol.

En informant directement le Manager (c’est le sens de la ligne de code), non seulement on sort bien du mode « menu ouvert », mais en cadeau, Swing fait tout le nécessaire pour bien refermer toutes les popups…

Un peu de contexte :

J’ai été amené à utiliser cela dans le cadre de mon travail, pour proposer à l’utilisateur un Drag’n’Drop des éléments de menus dans une toolbar, pour configurer ses boutons préférés. Or, pour plus de lisibilité il est pertinent de forcer la fermeture des popups pour permettre à l’utilisateur de déposer les éléments glissées dans la toolbar. Pendant longtemps, on a eu le problème du « mode menu ouvert », et notamment ça se traduit par le fait que le prochain clic est perdu : le Manager croit qu’un menu est ouvert, alors qu’on a tout fermé avec des setPopupMenuVisible, du coup le clic sert à sortir du mode, et n’est pas pris en compte par la gestion habituelle des événements. Conclusion : ce petit bug m’a bien énervé pendant un moment, et je suis parfaitement ravi d’avoir trouvé comment le résoudre !


Categorised as: Java


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *