Подтвердить что ты не робот

Как контролировать задержку всплывающей подсказки JavaFX?

Я играл с JavaFX Tooltip. Я понял, что лично для меня задержка между наведением на что-то и всплывающей подсказкой слишком велика. Взгляд на API показывает:

Обычно всплывающая подсказка "активируется", когда мышь перемещается над элементом управления. Обычно есть некоторая задержка между тем, когда подсказка становится "активированной" и когда она действительно отображается. Детали (например, количество задержек и т.д.) Оставлены для реализации Skin.

После дальнейшего расследования я не смог найти никакой возможности контролировать это поведение. Справочник по JavaFX CSS не содержит информации о времени задержки, и оценка getCssMetaData() также не помогла.

Я знаю, что есть способ управления всплывающими подсказками вручную через onMouseEntered и onMouseExited, но действительно ли нет другого пути? Или я упускаю очевидный вариант?

4b9b3361

Ответ 1

Для этого существует запрос функции: JDK-8090477 Настраиваемое время видимости для всплывающей подсказки.

Запрос функции в настоящее время запланирован для интеграции в Java 9. К проблеме, с которой я связан, прикреплен патч, который вы можете применить, чтобы позволить вам получить эту функциональность в более ранних версиях Java.

Другой вариант - просто создать собственный всплывающий элемент управления, используя один из методов:

Ответ 2

Я использую следующий взлом для этого через 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();
    }
}

Ответ 3

Я нахожу, что с вышеупомянутой реализацией по-прежнему существует задержка, которую я не могу объяснить.

Следующее работает для меня и полностью удаляет задержку:

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

Ответ 4

Расширяет подсказку или помещает класс Application. (Только 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);
        }
    }

Ответ 5

Привет, я не могу комментировать, пока не достиг репутации 50, но я хотел исправить ответ, данный Бруно Падо. Код, который он опубликовал, не работал в 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);
    }
}

Надеюсь, это поможет любому, кто хочет отредактировать задержку всплывающей подсказки, пока мы ждем JFX9.

Ответ 6

В Java 9 и позже вы можете сделать

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

Существует также свойство hideDelay для задержки между появлением всплывающей подсказки и ее hideDelay. Значения по умолчанию: 1 секунда для showDelay и 200 миллисекунд для hideDelay.

Ответ 7

Действительно, поскольку JavaFX 2, поведение всплывающих подсказок управляется внутри класса Tooltip статическим полем BEHAVIOR, которое не может быть изменено с использованием специальных публичных методов, поэтому пока. Если вы не хотите изобретать колесо или ждать Java 9, единственный способ - использовать Reflection 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);
    }
}

Ответ 8

В JavaFx 9 задержка всплывающей подсказки может быть установлена с помощью CSS. Это звучит извращенно, делать это в таблице стилей, но, вероятно, это то, что они имеют в виду, когда говорят "Детали (например, количество задержек и т.д.) Оставлены для реализации Skin".

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

Так что вы можете сделать что-то вроде этого:

.tooltip {
    -fx-show-delay: 250ms;
}