从EventHandler目标访问任意节点

时间:2019-06-28 09:03:34

标签: java javafx event-handling

我正在开发一个小型JavaFX应用程序。在此应用程序中,我具有以下组件:

BorderPane -> as the root element
        HBox top, bottom -> top and bottom regions
        VBox left, right -> left and right regions
        FlowPane center -> central region

单击中央区域时,我需要访问顶部区域中包含一些文本的节点。为了访问它,我像这样从事件的目标向上爬图:

public EventHandler<MouseEvent> fieldClicked = (MouseEvent e) -> {
    FlowPane target = (FlowPane)e.getTarget();
    BorderPane root = (BorderPane)target.getParent();
    HBox top = (HBox)root.getChildren().get(0);
    HBox top_left = (HBox)top.getChildren().get(0);
    Text total = (Text)top_left.getChildren().get(0);
    ObservableList<Node> dices = target.getChildren();
    /* Do some stuff with retrieved nodes */
};

除了迭代调用Node.getParent()

之外,还有没有更好和更少冗长的方法来访问场景图中的任意节点?

2 个答案:

答案 0 :(得分:2)

如果您不以其他方式存储字段,则不会。您可以附加一些id来通过CSS选择器(lookup)查找节点,但是在这种情况下,最好以其他方式做到这一点:

将需要访问的节点存储在字段中(或有效的最终局部变量,如果您在创建节点的同一作用域中注册了事件处理程序)。

...
private BorderPane root;
private HBox top;
private Text total;
private FlowPane target;

public EventHandler<MouseEvent> fieldClicked = (MouseEvent e) -> {
    ObservableList<Node> dices = target.getChildren();
    /* Do some stuff with fields */
};

private void initializeNodes() {
    ...
    total = new Text();
    top = new HBox(total);
    root.setTop(top);
    target = new FlowPane();
    root.setCenter(target);
    ...
}

最好还是尽可能将某些值的修改与场景的布局分离开来,因为这样可使您更轻松地重新布置场景,而不必担心事件处理程序通过up //正确导航场景。向下导航通过场景。此外,如果您在使用PaneGroup以外的“父母”的情况下使用方法,则会遇到麻烦。 ScrollPane的外观,因为ScrollPane的外观将content节点作为后代插入场景中,而不是作为子节点插入场景中,并且直到第一个布局通过后才执行此操作。


BTW:请注意,Event.getSource产生了触发事件处理程序的节点,而不是Event.getTarget

答案 1 :(得分:0)

要获取特定的Node,可以使用javafx.scene.Scene类的lookup()方法。

例如,您可以在包含一些文本的节点上设置一个ID,然后使用scene.lookup(“#theID”);找到它。

   public EventHandler<MouseEvent> fieldClicked = (MouseEvent e) -> {
    FlowPane target = (FlowPane)e.getTarget();
    Text total = (Text) target.getScene().lookup("#myTextID");

/* Do some stuff with retrieved nodes */
};

您可以通过以下方式设置的ID:

  Text text = new Text("My Text element somewhere");
  text.setId("myTextID");

我是JavaFX的新手,所以我也不知道这是否是最好的方法。但我希望这是您想要的。

顺便说一句,如果要进入根节点,可以改用:

   public EventHandler<MouseEvent> fieldClicked = (MouseEvent e) -> {
    FlowPane target = (FlowPane)e.getTarget();
    BorderPane root = (BorderPane) target.getScene().getRoot();

};

当FlowPane中有更多Elements时,这可能会有所帮助,那么您也不必经常调用Node.getParent()。

希望有帮助!