Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. «Я действительно не хочу дублировать код, например: myLabel1, myLabel2, ..., поскольку все они имеют одинаковый текст / подсказку / стиль.» Что если вы просто создать несколько ссылок, указывающих на один и тот же объект метки?
Или расширить Label, включив в него конструктор копирования:
public MyLabel(MyLabel aLabel) {
this.property1 = aLabel.property1;
this.property2 = aLabel.property2;
...
}
Затем в FXML с помощью copy:
<MyLabel fx:id="myLabel1"/>
<fx:copy source="myLabel1"/>
Невозможно добавить одно и то же Label
несколько раз в граф сцены. Это задокументировано в Node
( emphasis mine):
Узел может встречаться не более одного раза в любом месте графа сцены. В частности, узел должен появляться не более одного раза во всех следующих случаях: в качестве корневого узла в
Scene
, дочернихObservableList
вParent
или в качестве фрагментаNode
.Граф сцены не должен иметь циклов. Цикл будет существовать, если узел является предком самого себя в дереве, учитывая
Group
содержимоеObservableList
,Parent
childrenObservableList
иNode
отношений клипа, упомянутых выше.Если программа добавляет дочерний узел к
blockquote>Parent
(включаяGroup
,Region
и т. Д.), И этот узел уже является дочерним по отношению к другомуParent
или корнюScene
], узел автоматически (и без вывода сообщений) удаляется из своего прежнего родителя. Если программа пытается изменить граф сцены любым другим способом, который нарушает вышеуказанные правила, возникает исключение, попытка модификации игнорируется, и граф сцены восстанавливается в своем предыдущем состоянии.Выделенная часть объясняет, почему
Label
появляется только один раз при использовании<fx:reference>
.Решение
Единственное решение вашей проблемы - дублирование
Label
. Для этого можно использовать как минимум два варианта.Используйте
<fx:copy>
Один из способов сделать это, используя
<fx:copy>
( выделение шахта):Элемент
<fx:copy>
создает копию существующего элемента. Как и<fx:reference>
, он используется с атрибутомfx:id
или переменной сценария. Атрибут «source» элемента указывает имя объекта, который будет скопирован. Тип источника должен определять конструктор копирования, который будет использоваться для создания копии из исходного значения.На данный момент ни один из классов платформы JavaFX не предоставляет такой конструктор копирования, поэтому этот элемент предоставляется в первую очередь для использования разработчиками приложений. Это может измениться в будущем выпуске.
blockquote>Как указано в документации, использование
<fx:copy>
требует, чтобы класс имел конструктор копирования. В документации также говорится, что ни один из основных классов JavaFX не предоставляет конструкторы копирования. Это означает, что вам придется создать подклассLabel
и предоставить необходимый конструктор, как показано в ответе funkyjelly . Чтобы обеспечить актуальность свойств, вы можете связать свойства внутри конструктора: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. Эта опция может загромождать файл FXML, но не требует создания подкласса
Label
.