ejemplo - ¿Cómo controlar el retraso de la información sobre herramientas de JavaFX?
open dialog javafx (7)
De hecho, desde JavaFX 2, el comportamiento de la información sobre herramientas se gestiona internamente dentro de la clase Tooltip
mediante el campo estático BEHAVIOR
que no puede modificarse utilizando métodos públicos específicos, por lo tanto, por ahora. Si no desea reinventar la rueda o esperar a Java 9, La única manera es usar la API de Reflection como sigue:
/**
* 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);
}
}
Estaba jugando con JavaFX Tooltip . Me di cuenta de que, para mí, personalmente, la demora entre pasar sobre algo y la información sobre herramientas que aparece en realidad es demasiado larga. Una mirada en la API revela:
Normalmente, la información sobre herramientas se "activa" cuando el mouse se mueve sobre un Control. Por lo general, hay un cierto retraso entre el momento en que la información sobre herramientas se "activa" y el momento en que se muestra. Los detalles (como la cantidad de demora, etc.) se dejan a la implementación de Skin.
Después de una investigación adicional, no pude encontrar ninguna posibilidad de controlar este comportamiento. JavaFX CSS Reference no tiene información sobre el tiempo de retardo y una evaluación en tiempo de ejecución de getCssMetaData()
tampoco ayudó.
Sé que hay una forma de controlar la información sobre herramientas de forma manual a través de onMouseEntered
y onMouseExited
, pero ¿realmente no hay otra forma? ¿O me estoy perdiendo una opción obvia?
En Java 9 y posteriores, puedes hacer
Tooltip tooltip = new Tooltip("A tooltip");
tooltip.setShowDelay(Duration.seconds(3));
También hay una propiedad hideDelay
, para el retraso entre la información sobre herramientas que aparece y se oculta de nuevo. Los valores predeterminados son 1 segundo para el showDelay
y 200 milisegundos para el hideDelay
.
Encuentro que con la implementación anterior todavía hay un retraso que a veces no puedo explicar.
Lo siguiente ha funcionado para mí y eliminó el retraso por completo:
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();
}
});
}
Extiende la información sobre herramientas o la clase de aplicación. (Solo 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);
}
}
Hay una solicitud de función existente para esto: JDK-8090477 Tiempo de visibilidad personalizable para Tooltip .
La solicitud de función actualmente está programada para su integración en Java 9. Adjunto al problema que vinculé hay un parche que puede aplicar para permitirle obtener esta funcionalidad en versiones anteriores de Java.
Su otra opción es simplemente crear su propio control emergente usando una de las técnicas en:
Uso el siguiente truco para esto a través de Reflexión.
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();
}
}
Hola, no puedo hacer comentarios hasta que alcancé una reputación de 50, pero quería corregir la respuesta dada por Bruno Pado. El código que publicó no funcionó en JDK 8u121. El problema fue en qué campo declarado accedía. La solución es simple, cambie el índice de 1 a 0. Código de trabajo publicado a continuación:
/**
* <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);
}
}
Espero que esto ayude a cualquiera que busque editar el retardo de la información sobre herramientas mientras esperamos a JFX9.