JavaFx: одна и та же метка в двух (или более) местах в одном представлении - PullRequest
0 голосов
/ 15 января 2019

Я не знаю, пропустил ли я что-то, но мне не удалось этого добиться, у меня два и более ярлыка на одном и том же виде. Я не хочу дублировать его, просто используйте один и тот же ярлык с тем же текстом / подсказкой / стилем.

Простой пример:

<?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 голосов
/ 15 января 2019

Задача

Невозможно добавить одно и то же Label несколько раз в граф сцены. Это задокументировано Node ( выделение мое):

Узел может появляться не более одного раза в любом месте графа сцены. В частности, узел должен появляться не более одного раза во всех следующих случаях: в качестве корневого узла Scene, дочерних элементов ObservableList для Parent или в качестве фрагмента Node.

Граф сцены не должен иметь циклов. Цикл будет существовать, если узел является предком самого себя в дереве, учитывая упомянутые выше отношения Group content ObservableList, Parent children ObservableList и Node clip.

Если программа добавляет дочерний узел к Parent (включая Group, Region и т. Д.), И этот узел уже является дочерним по отношению к другому Parent или корню Scene, узел автоматически (и без вывода сообщений) удаляется из своего прежнего родителя. Если программа пытается изменить граф сцены любым другим способом, который нарушает вышеуказанные правила, возникает исключение, попытка модификации игнорируется, и Граф сцены восстанавливается в своем прежнем состоянии.

Выделенная часть объясняет, почему Label появляется только один раз при использовании <fx:reference>.

Решение

Единственное решение вашей проблемы - продублировать Label. Для этого есть как минимум два варианта.

Использование <fx:copy>

Один из способов сделать это с помощью <fx:copy> ( выделение мое):

Элемент <fx:copy> создает копию существующего элемента. Как и <fx:reference>, он используется с атрибутом fx:id или переменной сценария. Атрибут «source» элемента указывает имя объекта, который будет скопирован. Тип источника должен определять конструктор копирования, который будет использоваться для создания копии из исходного значения.

На данный момент ни один из классов платформы JavaFX не предоставляет такого конструктора копирования, поэтому этот элемент предоставляется в основном для использования разработчиками приложений. Это может измениться в будущем выпуске.

Как указано в документации, использование <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());
  }

}

Таким образом, вам нужно только ввести «мастер» Label, и любые обновления будут распространяться на все копии. Используя этот дизайн, вы должны иметь в виду, что связанные свойства не могут быть установлены напрямую; попытка установить связанное свойство приведет к исключениям. Возможно, вы захотите документировать, что конструктор будет связывать свойства, а не просто копировать значения.

Использовать привязки выражений

Другой вариант - связать необходимые свойства в файле FXML. Вы все равно будете создавать несколько Label s, но вам нужно будет только ввести "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.

0 голосов
/ 15 января 2019

"Я не хочу дублировать код, например: myLabel1, myLabel2, ..., поскольку все они имеют одинаковый текст / подсказку / стиль." Что если вы просто создать несколько ссылок, указывающих на один и тот же объект метки?

Или расширить Label, добавив конструктор копирования:

public MyLabel(MyLabel aLabel) {
this.property1 = aLabel.property1;
this.property2 = aLabel.property2;
...
}

Затем в FXML, используя копию:

<MyLabel fx:id="myLabel1"/>
<fx:copy source="myLabel1"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...