如何控制JavaFX Tooltip的延迟?
我正在玩JavaFX Tooltip 。 我意识到,就我个人而言,徘徊在某些东西和实际出现的工具提示之间的延迟太长了。 API中的内容显示:
通常,当鼠标在控件上移动时,工具提示会“激活”。 工具提示变为“激活”和实际显示之间通常存在一些延迟。 详细信息(例如延迟量等)留给Skin实现。
经过一些进一步的调查后,我无法找到任何控制此行为的可能性。 JavaFX CSS Reference没有关于延迟时间的信息, getCssMetaData()
的运行时评估也没有帮助。
我知道,有一种方法可以通过onMouseEntered
和onMouseExited
手动控制工具提示,但是真的没有办法吗? 或者我错过了一个明显的选择?
现有function请求: JDK-8090477 Tooltip的可自定义可见性计时 。
function请求当前已安排集成到Java 9.附加到我链接的问题是一个可以应用的补丁,以允许您在早期Java版本中获得此function。
您的另一个选择是使用以下技术之一创建自己的弹出控件:
- JavaFX 2自定义弹出窗格
我通过Reflection使用下一个hack
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(); } }
我发现,通过上述实现,有时我仍然无法解释。
以下内容对我有用,并完全消除了延迟:
public static void bindTooltip(final Node node, final Tooltip tooltip){ node.setOnMouseMoved(new EventHandler(){ @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 (){ @Override public void handle(MouseEvent event){ tooltip.hide(); } }); }
扩展工具提示或放置Application类。 (只有java8)
/** * * 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); } }
您好,我不能发表评论,直到我达到50的声誉,但我想纠正布鲁诺帕多给出的回应。 他发布的代码在JDK 8u121中不起作用。 问题在于它访问的声明字段。 修复很简单,将索引从1更改为0.工作代码发布如下:
/** * * 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时编辑工具提示延迟的人。
确实,自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); } }
在Java 9及更高版本中,您可以这样做
Tooltip tooltip = new Tooltip("A tooltip"); tooltip.setShowDelay(Duration.seconds(3));
还有一个hideDelay
属性,用于显示工具提示之间的延迟并再次隐藏它。 showDelay
的默认值为1秒, showDelay
的默认值为200毫秒。