Reputation: 20185
I was playing around with JavaFX's Tooltip
. I realized that for me personally the delay between hovering over something and the tooltip actually appearing is too long. A look in the API reveals:
Typically, the tooltip is "activated" when the mouse moves over a Control. There is usually some delay between when the Tooltip becomes "activated" and when it is actually shown. The details (such as the amount of delay, etc) is left to the Skin implementation.
After some further investigation, I was not able to find any possibility to control the delay. The JavaFX CSS Reference has no information about delay time and a runtime-evaluation of getCssMetaData()
did not help either.
I know that there is a way to control the tooltips manually via onMouseEntered(...)
and onMouseExited(...)
, but is there really no other way? Or am I missing an obvious solution?
Upvotes: 36
Views: 27934
Reputation: 647
It can also be done through SceneBuilder 22.0.0 by adding a Style "-fx-show-delay" to the tooltip node and setting it to say "100ms". This works for me.
Upvotes: 0
Reputation: 2574
In JavaFx 9, the tooltip delay can be set via CSS. It sounds pervert, to do this in a stylesheet, but probably this is what they mean when they say "The details (such as the amount of delay, etc) is left to the Skin implementation.".
https://docs.oracle.com/javase/9/docs/api/javafx/scene/doc-files/cssref.html#tooltip
So you can do something like this:
.tooltip {
-fx-show-delay: 250ms;
}
Upvotes: 6
Reputation: 209408
In Java 9 and later, you can do
Tooltip tooltip = new Tooltip("A tooltip");
tooltip.setShowDelay(Duration.seconds(3));
There is also a hideDelay
property, for the delay between the tooltip appearing and it being hidden again. The default values are 1 second for the showDelay
and 200 milliseconds for the hideDelay
.
Upvotes: 24
Reputation: 436
Hello, I can't comment until I reach a reputation of 50 but I wanted to correct the response given by Bruno Pado. The code he posted did not work in JDK 8u121. The issue was in which declared field it accessed. The fix is simple, change the index from 1 to 0. Working code posted below:
/**
* <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);
}
}
Hope this helps anyone who's looking to edit the tooltip delay while we wait for JFX9.
Upvotes: 3
Reputation: 44965
Indeed since JavaFX 2, the behavior of the tooltips is managed internally within the class Tooltip
by the static field BEHAVIOR
that cannot be modified using specific public methods so for now If you don't want to reinvent the wheel or wait for Java 9, the only way is by using the Reflection API as next:
/**
* 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);
}
}
Upvotes: 3
Reputation: 51
Extends Tooltip or put on Application class. (Only 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);
}
}
Upvotes: 5
Reputation: 91
I find that with the above implementation there's still a delay sometimes that I cannot explain.
The following has worked for me and removed the delay entirely:
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();
}
});
}
Upvotes: 9
Reputation: 159416
There is an existing feature request for this: JDK-8090477 Customizable visibility timing for Tooltip.
The feature request is currently scheduled for integration into Java 9. Attached to the issue I linked is a patch you can apply to allow you to get this functionality in earlier Java versions.
Your other option is just to create your own popup control using one of the techniques in:
Upvotes: 16
Reputation: 830
I use the next hack for this 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();
}
}
Upvotes: 51