簡體   English   中英

JavaFX 在場景圖控件上循環

[英]JavaFX looping over scenegraph controls

如何遍歷場景的控件? 我嘗試使用 getChildrenUnmodifiable() 但它只返回第一級兒童。

public void rec(Node node){

    f(node);

    if (node instanceof Parent) {
        Iterator<Node> i = ((Parent) node).getChildrenUnmodifiable().iterator();

        while (i.hasNext()){
            this.rec(i.next());
        }
    }
}

您需要遞歸掃描。 例如:

private void scanInputControls(Pane parent) {
    for (Node component : parent.getChildren()) {
        if (component instanceof Pane) {
            //if the component is a container, scan its children
            scanInputControls((Pane) component);
        } else if (component instanceof IInputControl) {
            //if the component is an instance of IInputControl, add to list
            lstInputControl.add((IInputControl) component);
        }
    }
}

這是我正在使用的amru 答案的修改版本,此方法為您提供特定類型的組件:

private <T> List<T> getNodesOfType(Pane parent, Class<T> type) {
    List<T> elements = new ArrayList<>();
    for (Node node : parent.getChildren()) {
        if (node instanceof Pane) {
            elements.addAll(getNodesOfType((Pane) node, type));
        } else if (type.isAssignableFrom(node.getClass())) {
            //noinspection unchecked
            elements.add((T) node);
        }
    }
    return Collections.unmodifiableList(elements);
}

獲取所有組件:

List<Node> nodes = getNodesOfType(pane, Node.class);

只獲取按鈕:

List<Button> buttons= getNodesOfType(pane, Button.class);

您還可以傳入一個謂詞,它允許進行任何類型的選擇。

Predicate<Node> p= n -> null ≃ n.getId() && n instanceof TextInputControl 

將獲得所有 TextFields 和 TextAreas。

你可以把它全部打包成一個接口,Java 8 風格,然后你只需要在 Pane 或其他容器中實現Parent getRoot()

@FunctionalInterface
public interface FXUIScraper {
    // abstract method.
    Parent getRoot();

    default List<Node> scrape( Predicate<Node> filter ) {
        Parent top = getRoot();

        List<Node> result = new ArrayList<>();
        scrape( filter, result, top );
        return result;
    }

    static void scrape( Predicate<Node> filter, List<Node> result, Parent top ) {
        ObservableList<Node> childrenUnmodifiable = top.getChildrenUnmodifiable();
        for ( Node node : childrenUnmodifiable ) {
            if ( filter.test( node ) ) {
                result.add( node );
            }
            if ( node instanceof Parent ) {
                scrape( filter, result, (Parent)node );
            }
        }
    }
}

假設您的窗格稱為窗格:

   FXUIScraper scraper = () ->pane;
   List<Node> textNodesWithId = 
        scraper.scrape(n -> null ≃ n.getId()
                    && n instanceof TextInputControl);

如果您有有意義的 id,例如實體的字段名稱或 json 對象中的鍵名稱,那么將結果處理成所需的形式就變得微不足道了。 github上有一個項目包含 fxuiscraper作為一個單獨的項目。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM