How to control the JavaFX Tooltip's delay?

23,861

Solution 1

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.

Solution 2

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();
    }
}

Solution 3

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:

Solution 4

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();
      }
   });
}

Solution 5

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;
}
Share:
23,861
Turing85
Author by

Turing85

Software Engineer, agile enthusiast, cloud-native fan Posts are my own and do not represent the opinion of my employer.

Updated on November 21, 2020

Comments

  • Turing85
    Turing85 over 3 years

    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?

  • Marco
    Marco almost 8 years
    a similar approach based however on a separate utility method to allow setting the global timing parameters on tooltips in JavaFX (Java 8) can be found here: gist.github.com/darmbrust/9559744d1b1dada434a3
  • apokryfos
    apokryfos about 7 years
    I think the point to take away here is that relying on the order that getDeclaredClasses is probably not a good idea since it is not always consistent between binary versions. If you know the class you're looking for then you can probably filter by that.
  • David
    David about 7 years
    This works well for my needs. And, as a bonus, it seems you only have to call it once for the whole application, not for every Tooltip instance you create.
  • Madrugada
    Madrugada over 5 years
    This will show a bunch of tooltips one after another while it will not hide anything. The tooltips won't disappear from my screen until I kill the process:))
  • JoschJava
    JoschJava over 5 years
    The reason is that the mouse event MouseMoved is being used. I changed it to MouseEntered. This has the disadvantage that it doesn't follow the cursor. What you can do though is change the MouseMoved function to MouseEntered, and in the mouseMoved function you set tooltip.setAnchorX(event.getScreenX()) and likewise with Y. I suggested an edit. If it isn't there yet, reply and I send you the code.
  • Shashanth
    Shashanth over 5 years
    Instead of suggesting an edit please post an answer of your own here. And add the link to this answer explain what's wrong with this answer, what do you've improved in your answer.
  • user3804769
    user3804769 over 5 years
    Bonus: you can do this for the DURATION of the tooltip too! The field name is "hideTimer" instead of "activationTimer".
  • SovietFrontier
    SovietFrontier about 5 years
    which imports are you using?
  • SovietFrontier
    SovietFrontier about 5 years
    which imports are you using?
  • Vivek V K
    Vivek V K over 3 years
    FYI, this is no longer needed since JavaFX9 see here: stackoverflow.com/questions/46408538/…
  • Manius
    Manius over 2 years
    Aren't the default values the other way around? Surely 200ms is not enough time to read any tooltip. Unless hide delay is something other than the total time it stays up before auto-hiding...
  • James_D
    James_D over 2 years
    @Manius Not according to the documentation, though I agree it seems weird.
  • Manius
    Manius about 2 years
    @David How does this work once for the whole application? That's not what I see so I think you're mistaken. (I wish you weren't!) It does take a Tooltip instance so it makes sense it would need to be done for every Tooltip. The other problem here though is that Tooltips can also be created in FXML, not just in code.
  • Manius
    Manius about 2 years
    This is by far the best Java 8 (only) solution, excellent job.
  • David
    David about 2 years
    @Manius, my comment is four years old and, sadly, I don't remember what my code looked like back then. I haven't used JavaFX since so I could not even begin to try and answer you. Sorry...
  • Manius
    Manius about 2 years
    Yeah that happens to me too, haha. The "hack" for Java 8 in another answer works fine though. You should use JFX again, it's awesome. :)