JavaFx:同一视图中两个(或更多)位置的相同标签
JavaFx: Same Label in two(or more) places in the same view
我不知道我是否错过了什么,但我无法做到这一点,我在同一个视图上有两次或更多次相同的标签。我真的不想复制它,只是使用具有相同 text/tooltip/style 的相同标签。
一个简单的例子:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.Label?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="Whosebug.dummy.Controller">
<Label fx:id="myLabel"/>
<!--<Label fx:id="myLabel"/>--> ofc this doesn't work.
<!--<Label fx:id="myLabel"/>-->
</AnchorPane>
如果我尝试使用 <fx:reference>
它只出现一次,如果我尝试使用 <fx:copy>
它说我需要一个复制构造函数,所以我想我只是错过了一些简单的解决方案。它应该存在。
注意:
我真的不想复制这样的代码:myLabel1、myLabel2、...,因为它们都具有相同的 text/tooltip/style.
我也知道我可以创建一个单独的 .fxml
文件,我在其中构建标签并通过 <fx:include>
使用它,但我更愿意在同一个 .fxml
中解决它,因为它是一个非常简单的事情我认为不值得为此创建一个新的.fxml
。
"I don't really want want to duplicate the code like: myLabel1, myLabel2, ..., since all of them are having the same text/tooltip/style." 如果您只是创建多个指向同一个标签对象的引用呢?
或者扩展 Label 以包含复制构造函数:
public MyLabel(MyLabel aLabel) {
this.property1 = aLabel.property1;
this.property2 = aLabel.property2;
...
}
然后在 FXML 中使用复制:
<MyLabel fx:id="myLabel1"/>
<fx:copy source="myLabel1"/>
问题
无法将相同 Label
多次添加到场景图中。 Node
(强调 我的)记录了这一点:
A node may occur at most once anywhere in the scene graph. Specifically, a node must appear no more than once in all of the following: as the root node of a Scene
, the children ObservableList
of a Parent
, or as the clip of a Node
.
The scene graph must not have cycles. A cycle would exist if a node is an ancestor of itself in the tree, considering the Group
content ObservableList
, Parent
children ObservableList
, and Node
clip relationships mentioned above.
If a program adds a child node to a Parent
(including Group
, Region
, etc) and that node is already a child of a different Parent
or the root of a Scene
, the node is automatically (and silently) removed from its former parent. If a program attempts to modify the scene graph in any other way that violates the above rules, an exception is thrown, the modification attempt is ignored and the scene graph is restored to its previous state.
强调的部分解释了为什么Label
在使用<fx:reference>
时只出现一次。
解决方案
解决您问题的唯一方法是复制 Label
。您至少可以使用两个选项来完成此操作。
使用<fx:copy>
一种方法是使用 <fx:copy>
(强调 我的):
The <fx:copy>
element creates a copy of an existing element. Like <fx:reference>
, it is used with the fx:id
attribute or a script variable. The element's "source" attribute specifies the name of the object that will be copied. The source type must define a copy constructor that will be used to construct the copy from the source value.
At the moment, no JavaFX platform classes provide such a copy constructor, so this element is provided primarily for use by application developers. This may change in a future release.
如文档中所述,使用 <fx:copy>
需要 class 具有复制构造函数。该文档还指出 none 的核心 JavaFX classes 提供了复制构造函数。这意味着您必须subclass Label
并提供所需的构造函数,如 所示。为确保属性保持最新,您可以在构造函数中绑定属性:
public class CopyableLabel extends Label {
public CopyableLabel(CopyableLabel label) {
// You only mentioned the text, tooltip, and style properties
// in your question. Bind more properties as needed.
textProperty().bind(label.textProperty());
tooltipProperty().bind(label.tooltipProperty());
styleProperty().bind(label.styleProperty());
}
}
这样你只需要注入 "master" Label
并且对它的任何更新都会传播到所有副本。使用这种设计时,您必须牢记不能直接设置绑定属性;尝试设置边界 属性 将导致异常。您可能想要记录构造函数将绑定属性,而不仅仅是复制值。
使用表达式绑定
另一种选择是在 FXML 文件中绑定所需的属性。您仍然会创建多个 Label
,但您只需要像以前一样注入 "master" Label
。
<VBox xmlns="http://javafx.com/javafx/" xmlns:fx="http://javafx.com/fxml/1">
<Label fx:id="master"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<!-- repeat as needed -->
</VBox>
这使用了 JavaFX FXML 的 expression binding 功能。此选项可能会使 FXML 文件混乱,但它不需要您创建 Label
.
的子 class
我不知道我是否错过了什么,但我无法做到这一点,我在同一个视图上有两次或更多次相同的标签。我真的不想复制它,只是使用具有相同 text/tooltip/style 的相同标签。
一个简单的例子:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.Label?>
<AnchorPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="Whosebug.dummy.Controller">
<Label fx:id="myLabel"/>
<!--<Label fx:id="myLabel"/>--> ofc this doesn't work.
<!--<Label fx:id="myLabel"/>-->
</AnchorPane>
如果我尝试使用 <fx:reference>
它只出现一次,如果我尝试使用 <fx:copy>
它说我需要一个复制构造函数,所以我想我只是错过了一些简单的解决方案。它应该存在。
注意: 我真的不想复制这样的代码:myLabel1、myLabel2、...,因为它们都具有相同的 text/tooltip/style.
我也知道我可以创建一个单独的 .fxml
文件,我在其中构建标签并通过 <fx:include>
使用它,但我更愿意在同一个 .fxml
中解决它,因为它是一个非常简单的事情我认为不值得为此创建一个新的.fxml
。
"I don't really want want to duplicate the code like: myLabel1, myLabel2, ..., since all of them are having the same text/tooltip/style." 如果您只是创建多个指向同一个标签对象的引用呢?
或者扩展 Label 以包含复制构造函数:
public MyLabel(MyLabel aLabel) {
this.property1 = aLabel.property1;
this.property2 = aLabel.property2;
...
}
然后在 FXML 中使用复制:
<MyLabel fx:id="myLabel1"/>
<fx:copy source="myLabel1"/>
问题
无法将相同 Label
多次添加到场景图中。 Node
(强调 我的)记录了这一点:
A node may occur at most once anywhere in the scene graph. Specifically, a node must appear no more than once in all of the following: as the root node of a
Scene
, the childrenObservableList
of aParent
, or as the clip of aNode
.The scene graph must not have cycles. A cycle would exist if a node is an ancestor of itself in the tree, considering the
Group
contentObservableList
,Parent
childrenObservableList
, andNode
clip relationships mentioned above.If a program adds a child node to a
Parent
(includingGroup
,Region
, etc) and that node is already a child of a differentParent
or the root of aScene
, the node is automatically (and silently) removed from its former parent. If a program attempts to modify the scene graph in any other way that violates the above rules, an exception is thrown, the modification attempt is ignored and the scene graph is restored to its previous state.
强调的部分解释了为什么Label
在使用<fx:reference>
时只出现一次。
解决方案
解决您问题的唯一方法是复制 Label
。您至少可以使用两个选项来完成此操作。
使用<fx:copy>
一种方法是使用 <fx:copy>
(强调 我的):
The
<fx:copy>
element creates a copy of an existing element. Like<fx:reference>
, it is used with thefx:id
attribute or a script variable. The element's "source" attribute specifies the name of the object that will be copied. The source type must define a copy constructor that will be used to construct the copy from the source value.At the moment, no JavaFX platform classes provide such a copy constructor, so this element is provided primarily for use by application developers. This may change in a future release.
如文档中所述,使用 <fx:copy>
需要 class 具有复制构造函数。该文档还指出 none 的核心 JavaFX classes 提供了复制构造函数。这意味着您必须subclass Label
并提供所需的构造函数,如
public class CopyableLabel extends Label {
public CopyableLabel(CopyableLabel label) {
// You only mentioned the text, tooltip, and style properties
// in your question. Bind more properties as needed.
textProperty().bind(label.textProperty());
tooltipProperty().bind(label.tooltipProperty());
styleProperty().bind(label.styleProperty());
}
}
这样你只需要注入 "master" Label
并且对它的任何更新都会传播到所有副本。使用这种设计时,您必须牢记不能直接设置绑定属性;尝试设置边界 属性 将导致异常。您可能想要记录构造函数将绑定属性,而不仅仅是复制值。
使用表达式绑定
另一种选择是在 FXML 文件中绑定所需的属性。您仍然会创建多个 Label
,但您只需要像以前一样注入 "master" Label
。
<VBox xmlns="http://javafx.com/javafx/" xmlns:fx="http://javafx.com/fxml/1">
<Label fx:id="master"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<Label text="${master.text}" tooltip="${master.tooltip}" style="${master.style}"/>
<!-- repeat as needed -->
</VBox>
这使用了 JavaFX FXML 的 expression binding 功能。此选项可能会使 FXML 文件混乱,但它不需要您创建 Label
.