JavaFX walk widget树

时间:2014-06-09 18:10:48

标签: widget javafx visitor

是否有一种简单(统一)的方法从定义的节点(可能来自Scene本身)递归下降JavaFX小部件树?

以下代码:

static class Visitor {
    public void visit(Node node){
        ...
    }
}

protected void walkWidgets(Node n, Visitor cb) {
    if (n instanceof Parent) {
        Parent p = (Parent) n;
        for (Node c : p.getChildrenUnmodifiable()) {
            walkWidgets(c, cb);
        }
    }
    cb.visit(n);
}

... 工作,因为"孩子"一些容器(例如:SplitPane,BorderPane等)在其子属性中列出

为了解决这个问题,我应该专门编写代码以允许所有不同小部件的所有怪癖。当您开始使用"标准"之外的小部件库时,这尤其令人讨厌。规定。

我错过了什么吗? (我当然希望如此!)

2 个答案:

答案 0 :(得分:1)

这似乎工作正常:它获取BorderPaneSplitPaneTabPane中的所有子节点。

import java.util.function.Consumer;

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class WalkComponentTree extends Application {

    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        root.setTop(new Label("Title"));

        SplitPane splitPane = new SplitPane();
        root.setCenter(splitPane);

        ListView<String> list = new ListView<>();
        list.getItems().addAll("One", "Two", "Three");

        TabPane tabPane = new TabPane();
        Tab tab1 = new Tab();
        tab1.setContent(new TextArea());
        Tab tab2 = new Tab();
        tab2.setContent(new Label("Tab 2"));
        tabPane.getTabs().addAll(tab1, tab2);

        splitPane.getItems().addAll(tabPane, list);

        Button button = new Button("Walk tree");
        button.setOnAction(event -> walkTree(root, node -> 
            System.out.println(node.getClass())));

        root.setBottom(button);

        Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();


    }

    private void walkTree(Node node, Consumer<Node> visitor) {
        visitor.accept(node);
        if (node instanceof Parent) {
            ((Parent) node).getChildrenUnmodifiable()
                .forEach(n -> walkTree(n, visitor));
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

请注意,您也可以使用node.lookupAll("*");,但这不太健壮,因为只有在css应用于节点后才能使用。

答案 1 :(得分:0)

在我看来,你说没有&#34;标准&#34;是正确的。浏览JavaFX场景图的方法。

一个原因是Tab不是来自Node,因此您无法从Parent.getChildrenUnmodifiable()获取标签列表。另一个原因是,ScrollPaneTitledPane不会在Parent.getChildrenUnmodifiable()中发布其内容节点。其他一些窗格AccordionSplitPaneToolbar也不会使用Parent.getChildrenUnmodifiable()发布他们的孩子。所以你需要自己处理。

有关详细信息,请参阅: Walking the JavaFX Scene Graph