JavaFX - 为什么将节点多次添加到窗格或不同的窗格会导致错误? [英] JavaFX - Why does adding a node to a pane multiple times or to different panes result in an error?
问题描述
我现在正在学习基本的 JavaFX,但我不明白我正在阅读的书中的这句话:不,像文本字段这样的节点只能添加到一个窗格中一次.添加一个节点多次转到一个窗格或转到不同的窗格会导致运行时错误."我可以从书中提供的 UML 图看出它是一个组合,但我不明白为什么(库类代码实现)是这样.
I'm learning basic JavaFX right now, and I don't understand this statement from the book I'm reading: "No, a node such as a text field can be added to only one pane and once. Adding a node to a pane multiple times or to different panes will cause a runtime error." I can see from the UML diagram the book provides that it is a composition, but I don't understand why (library class code implementation) that is.
例如,为什么这会导致编译错误?是不是在窗格中实例化了一个新的文本字段,因为它是一个组合?
For instance, why does this result in a compile error? Isn't a new text field instantiated within the pane since it's a composition?
FlowPane pane = new FlowPane();
StackPane pane2 = new StackPane();
TextField tf = new TextField();
pane.getChildren().add(tf);
pane.getChildren().add(tf);
另外,为什么下面运行但不显示放置在窗格中的文本字段?
Also, why does the following run but not show the text field placed in pane?
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();
推荐答案
这基本上是 API 设计方式的(有意的)结果.每个 Node
都有一个属性集合,包括一个 parent
属性(场景图中节点的唯一一个父节点),以及诸如 layoutX
和 layoutY
是节点相对于其父节点的坐标.因此,一个节点只能属于一个父节点,并且只能添加到父节点一次(因为它在父节点中只能有一个位置).以这种方式组织事物可以实现非常有效的布局过程.
This is basically a (deliberate) consequence of the way the API is designed. Each Node
has a collection of properties, including a parent
property (the - one and only one - parent of the node in the scene graph), along with properties such as layoutX
and layoutY
which are the coordinates of the node in relation to its parent. Consequently, a node can only belong to one parent, and can only be added to a parent once (as it can only have one location in the parent). Organizing things this way enables a very efficient layout process.
另一种思考方式:假设你的第一个代码块做了你想要的;所以文本字段 tf
在流窗格中出现了两次.您希望从 tf.getBoundsInParent()
得到什么结果?由于 tf
在父级中出现两次,API 将无法为此调用提供合理的值.
Another way to think of this: suppose your first code block did what you wanted; so the text field tf
appeared twice in the flow pane. What result would you expect to get from tf.getBoundsInParent()
? Since tf
appears twice in the parent, the API would not be able to give a sensible value for this call.
您在问题中的陈述有几个不准确之处:
There are a couple of inaccuracies in statements you make in your question:
例如,为什么这会导致编译错误?不是新的文本字段在窗格中实例化,因为它是一个组合?
For instance, why does this result in a compile error? Isn't a new text field instantiated within the pane since it's a composition?
首先,从技术上讲,这是聚合,而不是组合;虽然我不确定理解这些差异是否有助于您理解此时发生的事情.
First, technically, this is aggregation, not composition; though I'm not sure understanding the difference will aid your understanding of what is happening at this point.
其次,这里没有编译错误;您在运行时遇到错误(pane
检测到相同的 node
已添加两次;编译器无法检查这一点).
Second, there is no compile error here; you get an error at runtime (the pane
detects that the same node
has been added twice; the complier has no way to check this).
第三,父节点不会实例化您添加到它们的节点的副本.如果是这样,您将无法更改显示的节点的属性.例如,如果您的示例中的 FlowPane
在您调用 pane.getChildren().add(tf);
时实例化了一个新的 TextField
,并且然后显示该新文本字段,然后如果您随后调用 tf.setText("new text")
,它将没有任何效果,因为它不会更改 文本字段的文本>窗格
正在显示.
Third, parents do not instantiate copies of the nodes you add to them. If so, you wouldn't be able to change the properties of nodes that were displayed. For example, if the FlowPane
in your example instantiated a new TextField
when you called pane.getChildren().add(tf);
, and then displayed that new text field, then if you subsequently called tf.setText("new text")
, it would have no effect, as it would not be changing the text of the text field that pane
was displaying.
当您调用 pane.getChildren().add(...)
时,您传递了对要添加的节点的引用;该节点随后显示为窗格的子节点.任何其他实现都会产生非常违反直觉的行为.
When you call pane.getChildren().add(...)
you pass a reference to the node you want to be added; it is that node that is then displayed as a child of the pane. Any other implementation would produce pretty counter-intuitive behavior.
在您的第二个代码块中:
In your second code block:
pane.getChildren().add(tf);
pane2.getChildren().add(tf);
第二次调用将tf
的parent
属性隐式设置为pane2
;因此 tf
不再是 pane
的子元素.因此,此代码具有从第一个父项 pane
中删除 tf
的效果.据我所知,这种副作用没有记录在案,因此您可能应该避免编写这样的代码.
the second call implicitly sets the parent
property of tf
to pane2
; consequently tf
is no longer a child of pane
. So this code has the effect of removing tf
from the first parent, pane
. As far as I am aware, this side-effect is not documented, so you probably should avoid writing code like this.
这篇关于JavaFX - 为什么将节点多次添加到窗格或不同的窗格会导致错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!