Je jouais avec JavaFX Tooltip . J'ai réalisé que pour moi personnellement, le délai entre le survol de quelque chose et l'infobulle s'affichant trop longtemps est trop long. Un coup d'oeil dans l'API révèle:
En règle générale, l'info-bulle est "activée" lorsque la souris survole un contrôle. Il y a généralement un certain délai entre le moment où l'info-bulle devient "activée" et le moment où elle est affichée. Les détails (tels que le délai, etc.) sont laissés à l’implémentation de la peau.
Après une enquête plus approfondie, je n’ai pas trouvé de possibilité de contrôler ce comportement. Le Référence CSS JavaFX ne contient aucune information sur le délai et une évaluation de getCssMetaData()
à l'exécution ne l'a pas aidé non plus.
Je sais qu'il existe un moyen de contrôler les info-bulles manuellement via onMouseEntered
et onMouseExited
, mais n'y a-t-il vraiment pas d'autre moyen? Ou est-ce que je manque une option évidente?
Il existe déjà une demande de fonctionnalité pour cela: JDK-8090477 Synchronisation de visibilité personnalisable pour Tooltip .
L'intégration de Java 9 à la demande de fonctionnalité est actuellement prévue. Un correctif que vous pouvez appliquer pour vous permettre d'obtenir cette fonctionnalité dans les versions antérieures de Java est associé au problème que j'ai lié.
Votre autre option consiste simplement à créer votre propre contrôle contextuel à l’aide d’une des techniques suivantes:
J'utilise le prochain hack pour cela via Reflection
public static void hackTooltipStartTiming(Tooltip tooltip) {
try {
Field fieldBehavior = tooltip.getClass().getDeclaredField("BEHAVIOR");
fieldBehavior.setAccessible(true);
Object objBehavior = fieldBehavior.get(tooltip);
Field fieldTimer = objBehavior.getClass().getDeclaredField("activationTimer");
fieldTimer.setAccessible(true);
Timeline objTimer = (Timeline) fieldTimer.get(objBehavior);
objTimer.getKeyFrames().clear();
objTimer.getKeyFrames().add(new KeyFrame(new Duration(250)));
} catch (Exception e) {
e.printStackTrace();
}
}
Je trouve qu'avec la mise en œuvre ci-dessus, il y a encore parfois un retard que je ne peux pas expliquer.
Ce qui suit a fonctionné pour moi et a totalement supprimé le retard:
public static void bindTooltip(final Node node, final Tooltip tooltip){
node.setOnMouseMoved(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event) {
// +15 moves the tooltip 15 pixels below the mouse cursor;
// if you don't change the y coordinate of the tooltip, you
// will see constant screen flicker
tooltip.show(node, event.getScreenX(), event.getScreenY() + 15);
}
});
node.setOnMouseExited(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event){
tooltip.hide();
}
});
}
En Java 9 et ultérieur, vous pouvez faire
Tooltip tooltip = new Tooltip("A tooltip");
tooltip.setShowDelay(Duration.seconds(3));
Il existe également une propriété hideDelay
, pour le délai entre l'affichage de l'info-bulle et son masquage à nouveau. Les valeurs par défaut sont 1 seconde pour la showDelay
et 200 millisecondes pour la hideDelay
.
Bonjour, je ne peux pas commenter avant d'avoir atteint une réputation de 50 mais je voulais corriger la réponse donnée par Bruno Pado. Le code qu'il a posté ne fonctionnait pas dans JDK 8u121. Le problème était dans quel champ déclaré il accédait. Le correctif est simple, changez l'index de 1 à 0. Code de travail publié ci-dessous:
/**
* <p>
* Hack TooltipBehavior
*/
static {
try {
Tooltip obj = new Tooltip();
Class<?> clazz = obj.getClass().getDeclaredClasses()[0];
Constructor<?> constructor = clazz.getDeclaredConstructor(
Duration.class,
Duration.class,
Duration.class,
boolean.class);
constructor.setAccessible(true);
Object tooltipBehavior = constructor.newInstance(
new Duration(250), //open
new Duration(5000), //visible
new Duration(200), //close
false);
Field fieldBehavior = obj.getClass().getDeclaredField("BEHAVIOR");
fieldBehavior.setAccessible(true);
fieldBehavior.set(obj, tooltipBehavior);
}
catch (Exception e) {
Logger.error(e);
}
}
J'espère que cela aidera tous ceux qui cherchent à éditer le délai d'infobulle en attendant JFX9.
Étend l'info-bulle ou la classe d'application. (Uniquement Java8)
/**
* <p>
* Hack TooltipBehavior
*/
static {
try {
Tooltip obj = new Tooltip();
Class<?> clazz = obj.getClass().getDeclaredClasses()[1];
Constructor<?> constructor = clazz.getDeclaredConstructor(
Duration.class,
Duration.class,
Duration.class,
boolean.class);
constructor.setAccessible(true);
Object tooltipBehavior = constructor.newInstance(
new Duration(250), //open
new Duration(5000), //visible
new Duration(200), //close
false);
Field fieldBehavior = obj.getClass().getDeclaredField("BEHAVIOR");
fieldBehavior.setAccessible(true);
fieldBehavior.set(obj, tooltipBehavior);
}
catch (Exception e) {
Logger.error(e);
}
}
En effet depuis JavaFX 2, le comportement des info-bulles est géré en interne au sein de la classe Tooltip
par le champ statique BEHAVIOR
qui ne peut pas être modifié à l'aide de méthodes publiques spécifiques. Le seul moyen est d’utiliser l’API Reflection API comme suivant:
/**
* Hack allowing to modify the default behavior of the tooltips.
* @param openDelay The open delay, knowing that by default it is set to 1000.
* @param visibleDuration The visible duration, knowing that by default it is set to 5000.
* @param closeDelay The close delay, knowing that by default it is set to 200.
* @param hideOnExit Indicates whether the tooltip should be hide on exit,
* knowing that by default it is set to false.
*/
private static void updateTooltipBehavior(double openDelay, double visibleDuration,
double closeDelay, boolean hideOnExit) {
try {
// Get the non public field "BEHAVIOR"
Field fieldBehavior = Tooltip.class.getDeclaredField("BEHAVIOR");
// Make the field accessible to be able to get and set its value
fieldBehavior.setAccessible(true);
// Get the value of the static field
Object objBehavior = fieldBehavior.get(null);
// Get the constructor of the private static inner class TooltipBehavior
Constructor<?> constructor = objBehavior.getClass().getDeclaredConstructor(
Duration.class, Duration.class, Duration.class, boolean.class
);
// Make the constructor accessible to be able to invoke it
constructor.setAccessible(true);
// Create a new instance of the private static inner class TooltipBehavior
Object tooltipBehavior = constructor.newInstance(
new Duration(openDelay), new Duration(visibleDuration),
new Duration(closeDelay), hideOnExit
);
// Set the new instance of TooltipBehavior
fieldBehavior.set(null, tooltipBehavior);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
En JavaFx 9, le délai d'infobulle peut être défini via CSS. Cela semble pervers, de faire cela dans une feuille de style, mais c'est probablement ce qu'ils veulent dire quand ils disent "Les détails (tels que le délai, etc.) sont laissés à l'implémentation de Skin.".
https://docs.Oracle.com/javase/9/docs/api/javafx/scene/doc-files/cssref.html#tooltip
Donc, vous pouvez faire quelque chose comme ça:
.tooltip {
-fx-show-delay: 250ms;
}