Javafx Titlepane子项设置父项延迟

Javafx Titlepane子项设置父项延迟,javafx,Javafx,titlepane的孩子们很晚才让他们的父母(titlepane)离开。不像我使用的任何其他ui元素。示例代码: @Override public void start(Stage primaryStage) throws Exception{ Group root = new Group(); Scene scene = new Scene(root, 300, 275); primaryStage.setScene(scene); primaryStage.s

titlepane的孩子们很晚才让他们的父母(titlepane)离开。不像我使用的任何其他ui元素。示例代码:

@Override
public void start(Stage primaryStage) throws Exception{
    Group root = new Group();
    Scene scene = new Scene(root, 300, 275);
    primaryStage.setScene(scene);
    primaryStage.show();

    VBox vbox = new VBox(new Circle(30, Color.RED));
    TitledPane titledPane = new TitledPane("circle", vbox);
    root.getChildren().add(titledPane);
    System.out.println(titledPane.getParent());//parent is set
    System.out.println(vbox.getParent());//parent not set
}

虽然vbox立即设置了其父对象,但标题栏没有设置。这种行为是需要的(作为框架的效果)还是真的不一致?

不同之处在于,使用
VBox
时,您将其放置在
控件中。它不会添加到实际控件中,而是添加到其蒙皮(或蒙皮创建的结构的一部分)中,并且在实际显示之前不会构造该蒙皮。例如,如果将节点设置为标签的图形,则会发生类似的情况:

Label l = new Label();
Rectangle rect = new Rectangle(10, 10);
l.setGraphic(rect);
System.out.println(rect.getParent());
一般的规则是如果你打电话

parent.getChildren().add(node);

然后
node.getParent()
将立即设置为
parent
。如果调用不同的方法,例如
titledPane.setContent(…)
label.setGraphic(…)
,或
splitPane.getItems().add(…)
,则在显示控件之前,节点的父节点不会更改。

请考虑这个更新的示例,它(我认为)有助于演示发生了什么(詹姆斯的回答中已经解释了这一点):

样本的输出为:

Showing an empty scene with no content
Adding some content
Parent of node added directly to a child of a scene graph node: Group@27d5d559[styleClass=root]
Parent of node added only as content to a control: null
Manually requesting CSS application and a layout pass
Detected vbox parent changed to TitledPaneSkin$1@7cf1d24e[styleClass=content]
Parent of node added only as content to a control after triggering css and layout: TitledPaneSkin$1@7cf1d24e[styleClass=content]
如您所见,手动触发CSS应用程序和布局过程最终将实例化和初始化控件的外观,这将把作为内容添加到控件的节点放置到场景图中,并连接到节点的父节点。不过,一般来说,请小心手动触发CSS和布局过程,因为这可能会导致消极的性能影响如果您经常这样做,那么在这个简单的示例中,性能影响将完全可以忽略不计


import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class TitledPanSample extends Application {

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

    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 300, 275);
        stage.setScene(scene);

        System.out.println("Showing an empty scene with no content");
        stage.show();

        System.out.println("Adding some content");

        VBox vbox = new VBox(new Circle(30, Color.RED));
        vbox.parentProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("Detected vbox parent changed to " + newValue);
        });

        TitledPane titledPane = new TitledPane("circle", vbox);
        root.getChildren().add(titledPane);
        System.out.println("Parent of node added directly to a child of a scene graph node: " + titledPane.getParent());//parent is set
        System.out.println("Parent of node added only as content to a control: " + vbox.getParent());//parent not set

        System.out.println("Manually requesting CSS application and a layout pass");
        root.applyCss();
        root.layout();

        System.out.println("Parent of node added only as content to a control after triggering css and layout: " + vbox.getParent());//parent is set
    }
}