Загрузите файлы FXML с пользовательскими компонентами в JavaFX Scene Builder: атрибуты сбрасываются, а дочерние элементы удаляются

Я написал FXML-файл, в котором использую пользовательский компонент, расширяющий Group. При загрузке этого пользовательского компонента он должен добавить некоторые дочерние элементы (здесь: MyOverlayIcon) в свой список дочерних элементов и установить некоторые атрибуты с помощью кода (здесь: layoutX и layoutY).

MyIcon.java:

public class MyIcon extends Group {

/********************************
 * Graphic
 ********************************/
private ImageView graphic;
public ImageView getGraphic() {
    if(graphic == null) {
        graphic = new ImageView();
        getChildren().add(graphic);
        // Send image to back:
        graphic.toBack();
    }
    return graphic;
}

/********************************
 * DataPath
 ********************************/
private Property<String> dataPath;
public Property<String> dataPathProperty() {
    if (dataPath == null) {
        dataPath = new SimpleStringProperty();
    }
    return dataPath;
}
public String getDataPath() {
    return dataPathProperty().getValue();
}
public void setDataPath(String dataPath) {

    this.dataPathProperty().setValue(dataPath);
    getGraphic().setImage(new Image(dataPath));
}

/********************************
 * Overlays
 ********************************/
private ObservableList<MyOverlayIcon> overlays;
public ObservableList<MyOverlayIcon> getOverlays() {
    if (overlays == null) {
        overlays = FXCollections.observableArrayList();
        overlays.addListener(new ListChangeListener<MyOverlayIcon>() {

            @Override
            public void onChanged(ListChangeListener.Change<? extends MyOverlayIcon> c) {
                double moveX = 0.0;
                double moveY = 0.0;
                double iconWidth = 48.0;
                double iconHeight = 48.0;

                ObservableList<? extends MyOverlayIcon> icons = c.getList();
                MyOverlayIcon icon = icons.get(icons.size() - 1);

                String orientation = icon.getOrientation().toString(); 

                if(orientation.endsWith("EAST")) {
                    moveX = iconWidth / 2; 
                }
                if(orientation.startsWith("SOUTH")) {
                    moveY = iconHeight / 2;
                }

                icon.setLayoutX(moveX);
                icon.setLayoutY(moveY);
                getChildren().add(icon);
            }
        });
    }
    return overlays;
}

/********************************
 * Constructor
 ********************************/
public MyIcon(){}
}

MyOverlayIcon.java:

public class MyOverlayIcon extends MyIcon {

private EnumOrientation orientation;
public EnumOrientation getOrientation() {
    return orientation;
}
public void setOrientation(EnumOrientation orientation) {
    this.orientation = orientation;
    }

public MyOverlayIcon() {}
}

MyIconView.fxml:

<Group xmlns:fx="http://javafx.com/fxml">

    <MyIcon dataPath="@/images/User1_48.png">
        <overlays>
            <MyOverlayIcon dataPath="@/images/Remove_24.png" orientation="SOUTHWEST" />
            <MyOverlayIcon dataPath="@/images/Search1_24.png" orientation="NORTHEAST" />
        </overlays>
    </MyIcon>

</Group>

Когда я запускаю приложение в своей IDE, загружая этот файл fxml с помощью FXMLLoader, оно работает нормально: все новые дочерние элементы добавляются и отображаются правильно:

введите здесь описание изображения

Теперь я хочу изменить этот файл fxml с помощью Scene Builder. Но когда я загружаю файл с помощью Scene Builder, я вижу только пустой экземпляр группы:

введите здесь описание изображения

Только эти два обходных пути я узнал:

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

2.) Запустив Scene Builder в режиме отладки, я обнаружил, что любой атрибут, который я хочу изменить программно, должен быть сначала указан в fxml. В противном случае Scene Builder устанавливает значение по умолчанию.

Например, дети, которые я добавил динамически с помощью java-кода, один раз добавляются и снова удаляются, если компонент не указал никаких дочерних узлов в fxml. При добавлении любого пустого узла, такого как Pane, к моему компоненту в fxml, дочерние элементы не будут удалены, а также будут отображаться в Scene Builder.

С другими атрибутами все точно так же: значения, которые должны быть установлены кодом (здесь: layoutX и layoutY), применяются только в том случае, если я устанавливаю их в файле fxml с любым значением.

MyIconView_Workaround.fxml:

<Group xmlns:fx="http://javafx.com/fxml">

    <MyIcon dataPath="@/images/User1_48.png">
        <Pane />
        <overlays>
            <MyOverlayIcon dataPath="@/images/Remove_24.png" orientation="SOUTHWEST" layoutY="456">
                <Pane />
            </MyOverlayIcon>
            <MyOverlayIcon dataPath="@/images/Search1_24.png" orientation="NORTHEAST"  layoutX="123">
                <Pane />
            </MyOverlayIcon>
        </overlays>
    </MyIcon>

</Group>

введите здесь описание изображения

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


У кого-нибудь есть идея, как загрузить файл fxml с помощью Scene Builder, содержащего пользовательский компонент, который динамически добавляет дочерние элементы с помощью java-кода к себе и изменяет их (или его) значения атрибутов, не указывая их в fxml?


person Daniel    schedule 09.04.2013    source источник
comment
какой конструктор сцен вы используете?   -  person Kalaschni    schedule 19.04.2013
comment
Пробовал с 1.0, но обнаружил, что с 1.1 работает! (см. ответ ниже)   -  person Daniel    schedule 22.04.2013


Ответы (1)


Я нашел это сообщение на форуме oracle полгода назад.

Там сказано, что это ошибка, и я обнаружил, что в новейшей версии конструктора сцен (Scene Builder 1.1 Early Access) исправлено.

С этой версией все работает как надо. :)

Спасибо за вашу помощь!

person Daniel    schedule 22.04.2013
comment
Привет Даниэль, как включить режим отладки в Scene Builder? - person amru; 30.04.2013
comment
Я думаю, что в Scene Builder нет собственного режима отладки, я сделал это с помощью функции удаленной отладки из Eclipse IDE. Я выполнил что-то вроде java -Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y -cp %CLASSPATH% com.oracle.javafx.authoring.Main, где CLASSPATH был установлен в строку, не включающую все jar-файлы в каталоге SceneBuilder + целевой каталог моих собственных скомпилированных классов, которые я использовал в этом FXML-файле. Затем настройте отладочную конфигурацию в Eclipse IDE... Возможно, вы можете попробовать эту ссылку: sdqweb.ipd .kit.edu/wiki/Remote_Debugging_mit_Eclipse С уважением, Даниэль - person Daniel; 30.05.2013