可以将上下文菜单添加到滚动窗格,但不能添加到其他类型的窗格。为什么?
2 回答
FXML 的工作原理
FXML 通过使用反射(或使用专门的构建器类)对 Java API 进行内省来工作。有关 FXML 作品的更多信息,请参阅 FXML简介文档。
为什么不能使用 FXML 标记在 JavaFX 的窗格上定义 ContextMenus
控件有一个contextMenu 属性。ScrollPane是一个控件。其他窗格类型(例如StackPane)不是控件。由于在这些其他窗格类型中没有相应的属性可以设置为包含对 contextMenu 的引用,因此您无法使用 FXML 在这些窗格类型上定义 contextMenu。
出于类似的原因,您也不能在窗格上定义工具提示。
如何为 FXML 控制器中的窗格定义 ContextMenu
您仍然可以使用 contextMenu show API 通过代码在窗格(以及任何其他非控件的任意节点)上设置上下文菜单,例如通过将以下代码放置在 FXML 控制器中。
@FXML StackPane stack;
// . . .
public void initialize() {
final ContextMenu contextMenu = new ContextMenu(new MenuItem("xyzzy"));
stack.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
contextMenu.show(
stack,
mouseEvent.getScreenX(),
mouseEvent.getScreenY()
);
}
});
}
为什么不添加 ContextMenu 属性
节点可以有一个 contextMenu 属性,这将允许通过 FXML 标记在窗格上定义 ContextMenus。
Node没有 contextMenu 属性而 Control 有的原因是因为 ContextMenu 本身就是一个 Control 。将 ContextMenu 属性添加到节点意味着 JavaFX 实现的核心场景图模型代码将依赖于控制模块(它将依赖于场景图模块),因此是循环依赖。这将阻止发布包含核心 JavaFX 场景图和渲染引擎但不包含控件的非常轻量级的 Java 运行时系统(不是今天有人发布这样的系统)。
如何提交功能请求
如果您认为应该更改系统以允许使用 SceneBuilder 在任意窗格上定义上下文菜单,那么您可以针对 JavaFX 问题跟踪器提交功能请求(如果这样做,请在功能请求中包含返回此问题的链接) .
如果场景图中的每个节点都想打开上下文菜单,则所描述的打开弹出窗口的方法会导致打开多个弹出窗口。绝对需要消费事件。
另请参阅Using FXML to Create ContextMenu within a Pane 中的讨论它为这个问题提供了有效的答案。
顺便说一句,应该改用 Node.onContextMenuRequested(...) ,是吗?