JavaFX - 为什么多次向窗格添加节点或向不同的窗格添加节点会导致错误?

时间:2014-12-29 21:36:48

标签: java javafx javafx-2

我现在正在学习基本的JavaFX,我不明白我正在阅读的书中的这句话:“不,像文本字段这样的节点只能添加到一个窗格而且只能添加一次。窗格多次到窗格或不同的窗格都会导致运行时错误。“我可以从UML图中看到本书提供的它是一个组合,但我不明白为什么(库类代码实现)。

例如,为什么会导致编译错误?是不是在窗格中实例化了一个新的文本字段,因为它是一个组合?

FlowPane pane = new FlowPane();
StackPane pane2 = new StackPane();
TextField tf = new TextField();
pane.getChildren().add(tf);
pane.getChildren().add(tf);

另外,为什么以下运行但不显示放置在窗格中的文本字段?

FlowPane pane = new FlowPane();
StackPane pane2 = new StackPane();
TextField tf = new TextField();
pane.getChildren().add(tf);
pane2.getChildren().add(tf);

primaryStage.setScene(new Scene(pane));
primaryStage.show();

2 个答案:

答案 0 :(得分:4)

这基本上是API设计方式的(故意)结果。每个Node都有一组属性,包括parent属性(场景图中的一个且只有一个 - 节点的父节点),以及layoutX和{等属性{1}}这是节点相对于其父节点的坐标。因此,节点只能属于一个父节点,并且只能添加到父节点一次(因为它只能在父节点中有一个位置)。以这种方式组织事物可以实现非常有效的布局过程。

另一种思考方式:假设你的第一个代码块做了你想要的;所以文本字段layoutY在流程窗格中出现两次。您期望从tf获得什么结果?由于tf.getBoundsInParent()在父级中出现两次,因此API无法为此次调用提供合理的值。

您在问题中的陈述中有一些不准确之处:

  

例如,为什么会导致编译错误?不是新的   文本字段在窗格中实例化,因为它是一个组合?

首先,从技术上讲,这是聚合,而不是组合;虽然我不确定理解差异会帮助你理解目前发生的事情。

其次,这里没有编译错误;您在运行时收到错误(tf检测到已添加两次相同的pane;编译器无法检查此错误。

第三,父母不会实例化您添加到其中的节点的副本。如果是这样,您将无法更改显示的节点的属性。例如,如果示例中的node在您调用FlowPane时实例化了新的TextField,然后显示了该新文本字段,那么如果您随后调用了pane.getChildren().add(tf);,那么没有效果,因为它不会改变tf.setText("new text")正在显示的文本字段的文本。

当您致电pane时,您会传递对您要添加的节点的引用;然后,该节点将显示为窗格的子节点。任何其他实现都会产生相当反直觉的行为。

在你的第二个代码块中:

pane.getChildren().add(...)

第二个调用隐式将pane.getChildren().add(tf); pane2.getChildren().add(tf); 的{​​{1}}属性设置为parent;因此tf不再是pane2的孩子。因此,此代码可以从第一个父tf中删除pane。据我所知,这种副作用没有记录,所以你可能应该避免编写这样的代码。

答案 1 :(得分:0)

试试这个:

TextField tf = new TextField();
TextField tf2 = new TextField();
pane.getChildren().add(tf);
pane.getChildren().add(tf2);

您无法两次添加同一节点的原因是只能在gui中查看具有相同规格和尺寸的一个节点。这就像将相同的蓝色圆圈复制到原始的蓝色圆圈上一样。对于用户来说,它看起来是一样的,但它占用了更多的内存。