java 如何控制 JavaFX Tooltip 的延迟?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26854301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:45:44  来源:igfitidea点击:

How to control the JavaFX Tooltip's delay?

javacssjavafx-8fxml

提问by Turing85

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:

我在玩JavaFX 的Tooltip. 我意识到,就我个人而言,悬停在某物上和实际出现的工具提示之间的延迟太长了。API 中的外观显示:

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 Referencehas no information about delay time and a runtime-evaluation of getCssMetaData()did not help either.

经过一些进一步的调查,我找不到任何控制延迟的可能性。在JavaFX的CSS参考没有关于延迟时间和运行时间,评价信息getCssMetaData()没有帮助。

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?

我知道,有一种方法可以通过onMouseEntered(...)和手动控制工具提示onMouseExited(...),但真的没有其他方法吗?或者我错过了一个明显的解决方案?

采纳答案by jewelsea

There is an existing feature request for this: JDK-8090477 Customizable visibility timing for Tooltip.

有一个现有的功能请求:JDK-8090477 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.

该功能请求目前计划集成到 Java 9 中。附加到我链接的问题中是一个补丁,您可以应用该补丁以允许您在较早的 Java 版本中获得此功能。

Your other option is just to create your own popup control using one of the techniques in:

您的另一个选择是使用以下技术之一创建自己的弹出控件:

回答by Igor Luzhanov

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

回答by James_D

In Java 9 and later, you can do

在 Java 9 及更高版本中,您可以执行

Tooltip tooltip = new Tooltip("A tooltip");
tooltip.setShowDelay(Duration.seconds(3));

There is also a hideDelayproperty, for the delay between the tooltip appearing and it being hidden again. The default values are 1 second for the showDelayand 200 milliseconds for the hideDelay.

还有一个hideDelay属性,用于工具提示出现和再次隐藏之间的延迟。的默认值为 1 秒, 的默认值为showDelay200 毫秒hideDelay

回答by Aleks Messier

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

回答by Bruno Prado

Extends Tooltip or put on Application class. (Only java8)

扩展工具提示或放入应用程序类。(仅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);
        }
    }

回答by d_scalzi

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:

您好,在达到 50 的声誉之前,我无法发表评论,但我想更正 Bruno Pado 的回复。他发布的代码在 JDK 8u121 中不起作用。问题在于它访问的声明字段。修复很简单,将索引从 1 更改为 0。工作代码发布如下:

/**
 * <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.

希望这可以帮助那些希望在我们等待 JFX9 时编辑工具提示延迟的人。

回答by Nicolas Filotto

Indeed since JavaFX 2, the behavior of the tooltips is managed internally within the class Tooltipby the static field BEHAVIORthat 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 APIas next:

事实上,从 JavaFX 2 开始,工具提示的行为在类内部Tooltip由静态字段管理BEHAVIOR,不能使用特定的公共方法修改,所以现在如果你不想重新发明轮子或等待 Java 9,唯一的方法是通过使用反射 API如下:

/**
 * 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);
    }
}

回答by Franz Deschler

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.".

在 JavaFx 9 中,工具提示延迟可以通过 CSS 设置。在样式表中执行此操作听起来很不正常,但可能这就是他们说“细节(例如延迟量等)留给皮肤实现。”的意思。

https://docs.oracle.com/javase/9/docs/api/javafx/scene/doc-files/cssref.html#tooltip

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