我不知道我是否会错过任何东西,但我无法做到这一点,在同一视图上我具有相同的标签两次或更多次。我真的不想复制它,只是使用具有相同文本/工具提示/样式的相同标签。
一个简单的例子:
<?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="stackoverflow.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,...这样的代码,因为它们都具有相同的文本/工具提示/样式。
我也知道我可以创建一个单独的.fxml
文件,在其中创建标签并通过<fx:include>
使用它,但我宁愿在同一.fxml
中解决它,因为它确实简单的事情,我认为不应该为此单独创建一个新的.fxml
。
答案 0 :(得分:3)
不可能多次向场景图添加相同 Label
。 Node
(强调我的)记录了这一点:
一个节点最多可以在场景图中的任何位置出现一次。具体来说,节点在以下所有所有项中的出现不得超过一次:作为
Scene
的根节点,ObservableList
的子节点Parent
或{ {1}}。场景图不能有循环。如果节点是树中自身的祖先,则考虑
Node
内容Group
,ObservableList
子Parent
和ObservableList
剪辑关系,就会存在一个循环上面提到过。如果程序将子节点添加到
Node
(包括Parent
,Group
等)并且该节点已经是其他{{1} }或Region
的根,该节点会自动(并以静默方式)从其先前的父节点中移除。如果程序尝试以其他违反上述规则的方式修改场景图,则抛出异常,修改尝试将被忽略,场景图将还原到其先前状态。
强调的部分说明了为什么使用Parent
时Scene
只出现一次。
解决您问题的唯一方法是复制Label
。您至少可以使用两个选项来完成此操作。
<fx:reference>
使用<fx:copy>
(强调我的)的一种方法:
Label
元素创建一个现有元素的副本。与<fx:copy>
类似,它与<fx:copy>
属性或脚本变量一起使用。元素的“源”属性指定将要复制的对象的名称。 源类型必须定义一个复制构造函数,该构造函数将用于从源值构造副本。目前,没有JavaFX平台类提供这种复制构造函数,因此主要提供该元素供应用程序开发人员使用。在以后的版本中可能会更改。
如文档中所述,使用<fx:reference>
要求该类具有副本构造函数。该文档还指出,核心JavaFX类都不提供副本构造函数。这意味着您必须继承fx:id
并提供所需的构造函数,如funkyjelly's answer所示。为了确保属性保持最新,您可以将属性绑定到构造函数中:
<fx:copy>
这样,您只需注入“母版” Label
,对它的任何更新都将传播到所有副本。使用这种设计时,必须牢记绑定属性不能直接设置;尝试设置绑定属性将导致异常。您可能想要记录构造函数将绑定属性,而不仅仅是复制值。
另一个选择是将所需的属性绑定到FXML文件中。您仍将创建多个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());
}
}
,但是您只需像以前一样注入“主” Label
。
Label
这使用JavaFX FXML的expression binding功能。此选项可能会使FXML文件混乱,但是不需要您创建Label
的子类。
答案 1 :(得分:0)
“我真的不想复制像myLabel1,myLabel2等这样的代码,因为它们都具有相同的文本/工具提示/样式。” 只是创建指向同一标签对象的多个引用?
或扩展Label以包括复制构造函数:
public MyLabel(MyLabel aLabel) {
this.property1 = aLabel.property1;
this.property2 = aLabel.property2;
...
}
然后在FXML中使用副本:
<MyLabel fx:id="myLabel1"/>
<fx:copy source="myLabel1"/>