JavaFX - 为什么将节点多次添加到窗格或不同的窗格会导致错误? [英] JavaFX - Why does adding a node to a pane multiple times or to different panes result in an error?

查看:18
本文介绍了JavaFX - 为什么将节点多次添加到窗格或不同的窗格会导致错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在学习基本的 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 属性(场景图中节点的唯一一个父节点),以及诸如 layoutXlayoutY 是节点相对于其父节点的坐标.因此,一个节点只能属于一个父节点,并且只能添加到父节点一次(因为它在父节点中只能有一个位置).以这种方式组织事物可以实现非常有效的布局过程.

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);

第二次调用将tfparent属性隐式设置为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆