JavaFx:同一视图中两个(或多个)位置的相同标签

时间:2019-01-15 09:31:53

标签: java javafx javafx-8 fxml

我不知道我是否会错过任何东西,但我无法做到这一点,在同一视图上我具有相同的标签两次或更多次。我真的不想复制它,只是使用具有相同文本/工具提示/样式的相同标签。

一个简单的例子:

<?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

2 个答案:

答案 0 :(得分:3)

问题

不可能多次向场景图添加相同 LabelNode强调我的)记录了这一点:

  

一个节点最多可以在场景图中的任何位置出现一次。具体来说,节点在以下所有所有项中的出现不得超过一次:作为Scene的根节点,ObservableList的子节点Parent或{ {1}}。

     

场景图不能有循环。如果节点是树中自身的祖先,则考虑Node内容GroupObservableListParentObservableList剪辑关系,就会存在一个循环上面提到过。

     

如果程序将子节点添加到Node(包括ParentGroup等)并且该节点已经是其他{{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"/>