如何解决JavaFX ContextMenu源节点?

How to solve JavaFX ContextMenu source node?

我在 FXML 文件中创建的用户界面中有多个 CheckBox

<CheckBox..>
  <contextMenu>
    <ContextMenu>
      <items>
        <MenuItem text="%uncheckall" onAction="#uncheckAll" />
        <MenuItem text="%checkall" onAction="#checkAll" />
      </items>
    </ContextMenu>
  </contextMenu>
</CheckBox>
...

所有 CheckBoxes 使用相同的方法,即 uncheckAllcheckAll。 我如何 return ContextMenu 的来源 NodeCheckBoxEvent 的处理方法中?

@FXML private void uncheckAll(Event event) {
  MenuItem mni = (MenuItem)event.getSource();
  ContextMenu cm = mni.getParentPopup();
  ...???
}

API 中似乎没有任何内容可用于获取 Node 的上下文菜单的所有者,但是 ContextMenu 的祖先 class有方法 setUserData。您可以将CheckBox设置为ContextMenu用户数据。这是一个仅使用代码的示例,即不使用 FXML。

CheckBox cb = new CheckBox("check");
MenuItem mi = new MenuItem("menu item");
mi.setOnAction(this::uncheckAll);
ContextMenu cm = new ContextMenu(mi);
cm.setUserData(cb);
cb.setContextMenu(cm);

然后,在您的 uncheckAll 方法中,您可以通过方法 getUserData 检索 CheckBox

@FXML private void uncheckAll(Event event) {
    MenuItem mi = (MenuItem) event.getSource();
    ContextMenu cm = mi.getParentPopup();
    CheckBox cb = (CheckBox) cm.getUserData();
}

编辑

在 FXML 中,只需将 userData 属性添加到 ContextMenu 标签即可。

<ContextMenu userData="cbxGroup1">

您实际上可能不需要弄清楚上下文菜单附加到哪个复选框。

您的任务可能可以通过将标准 fxml 注入控制器来完成。

在您的 fxml 中为复选框分配 fx:id:

fx:id="cb"

将它注入你的控制器:

@FXML private CheckBox cb;

加载 fxml 后,您可以在控制器的任何位置通过名称引用复选框 cb,包括在事件处理程序实现中。

@FXML private void uncheckAll(Event e) {
    // you can refer to cb directly here.
}

由于您的界面中有多个复选框,请多次执行上述所有操作,包括事件处理程序定义。

如果您想共享事件处理程序的公共处理,您可以调用一个单独的方法,将引用传递给与事件处理程序关联的复选框。

@FXML private CheckBox cb1;
@FXML private CheckBox cb2;

@FXML private void uncheckAllForCb1(Event e) {
    uncheckAll(cb1);
}

@FXML private void uncheckAllForCb2(Event e) {
    uncheckAll(cb2);
}

private void uncheckAll(CheckBox sourceBox) {
    // take action for box.
}