我正在努力让JavaFX Pane
(VBox
在我的情况下,但我认为不重要),ContextMenu
行为正确。
我找到了这两个问题:why Pane
s can't have ContextMenu
s和How to create ContextMenu
within a Pane
。
我对这两个解决方案(非常相似)的问题是,如果单击窗格,上下文菜单会正确消失,但如果我在该窗格中的控件内单击,它就不会消失。观察此缺陷的最简单方法是使用TextField
创建此类窗格。右键单击窗格以显示上下文菜单,然后单击内部到TextField
以关注它。虽然适当的上下文菜单会在此时消失,但这个“入侵”的上下文菜单(缺少一个更好的术语)很乐意保留在它的位置,可能会阻止用户查看他们试图填写的文本字段。
现在,我知道我可以在我的窗格上的每个控件的focused
属性中添加一个更改侦听器,但这感觉多余。有没有更好的方法可以确保在选择窗格中的控件时隐藏上下文菜单(或者更准确地说 - 当用户在上下文菜单外的拥有窗口中的任意位置单击鼠标时)?
到目前为止我尝试了什么并且不起作用 -
focused
属性添加更改侦听器 - 如果其中一个子窗口focused
属性中添加更改侦听器 - 单击外部菜单时,上下文菜单的焦点不会更改。 答案 0 :(得分:3)
好的,所以在对JavaFX的源代码进行一些挖掘后,我发现了这种解决方法(这就是"解决了#34;正常控件的这个问题)。只需添加以下代码行 -
contextMenu.setImpl_showRelativeToWindow(true);
现在,我知道不鼓励使用内部实现方法,因为它们可能会消失,但这是我找到的唯一解决方案。如果有人有更好的解决方案,我会很高兴听到它,但我怀疑这只是一个应该提交的错误(即 - 应该有一种方法在设置上下文菜单时使用showRelativeToWindow
机制在窗格上)。
我想一个更安全的解决方案是设置上下文菜单的一次性控制(不在场景图中),但我不知道这是否会产生任何不必要的副作用:
Label throwaway = new Label(); // No special reason for using Label, could be any Control.
throwaway.setContextMenu(contextMenu); // note that this is the only place `throwaway` is used, it is never added to the scene graph
// or referenced again, but just setting the context menu on a control solves the problem.
修改强>
在挖掘了更多我发现this和讨论的解决方案之后 - 你应该调用show
方法重载,它需要一个窗口,而不是一个节点!不是很清楚,但它有效:
myPane.setOnContextMenuRequested(event ->
contextMenu.show(myPane.getScene().getWindow(), event.getScreenX(), event.getScreenY())
);