Как контролировать задержку всплывающей подсказки JavaFX?
Я играл с JavaFX Tooltip. Я понял, что лично для меня задержка между наведением на что-то и всплывающей подсказкой слишком велика. Взгляд на API показывает:
Обычно всплывающая подсказка "активируется", когда мышь перемещается над элементом управления. Обычно есть некоторая задержка между тем, когда подсказка становится "активированной" и когда она действительно отображается. Детали (например, количество задержек и т.д.) Оставлены для реализации Skin.
После дальнейшего расследования я не смог найти никакой возможности контролировать это поведение. Справочник по JavaFX CSS не содержит информации о времени задержки, и оценка getCssMetaData()
также не помогла.
Я знаю, что есть способ управления всплывающими подсказками вручную через onMouseEntered
и onMouseExited
, но действительно ли нет другого пути? Или я упускаю очевидный вариант?
Ответы
Ответ 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;
}