2014-11-10 2 views
23

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

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

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

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

ответ

14

Для этого есть функция: JDK-8090477 Customizable visibility timing for Tooltip.

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

другое Ваш вариант просто создать свой собственный контроль всплывающую с использованием одного из методов в:

37

Я использую следующий хак для этого с помощью 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(); 
    } 
} 
+0

Это хорошо работает для моих нужд. И, как бонус, кажется, вам нужно только называть его один раз для всего приложения, а не для каждого созданного вами примера Tooltip. – David

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

Расширяет Tooltip или поставить на класс 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); 
     } 
    } 
+2

аналогичный подход, основанный, однако, на отдельном утилите, позволяющем устанавливать глобальные параметры времени на всплывающих подсказках в JavaFX (Java 8), можно найти здесь: https://gist.github.com/darmbrust/9559744d1b1dada434a3 – Marco

2

Действительно, так как 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); 
    } 
} 
2

Здравствуйте, я не могу комментировать, пока не достигнет репутацию 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.

+1

Я думаю, что точка уберите здесь то, что полагаться на порядок, который 'getDeclaredClasses', вероятно, не очень хорошая идея, поскольку он не всегда согласован между двоичными версиями. Если вы знаете класс, который ищете, вы можете, возможно, фильтровать его. – apokryfos

Смежные вопросы