【问题标题】:Load FXML files with custom components in JavaFX Scene Builder: Attributes are reset and children removed在 JavaFX Scene Builder 中使用自定义组件加载 FXML 文件:重置属性并删除子项
【发布时间】:2013-04-01 01:49:08
【问题描述】:

我编写了一个 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 中启动应用程序时,使用 FXMLLoader 加载这个 fxml 文件,它工作正常:所有新子项都已添加并正确显示:

现在我想用 Scene Builder 修改这个 fxml 文件。 但是当我使用 Scene Builder 加载文件时,我只看到一个空组实例:

我只发现了这两种解决方法:

1.) 显式调用将子代添加到子列表的方法(例如,在属性的 setter 方法中),添加并显示子代,但仅在通过修改某些内容而不是在调用此 setter 时加载文件时的开始。

2.) 在调试模式下运行 Scene Builder 时,我发现我想以编程方式修改的任何属性都必须首先在 fxml 中指定。否则,Scene Builder 会将其值设置为默认值。

例如,如果组件没有在 fxml 中指定任何子节点,则我通过 java-code 动态添加的子节点一旦添加并再次删除。 在 fxml 中将任何空节点(如 Pane)添加到我的组件中,子级不会被删除,并且也会显示在 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>

//编辑:如果您看不到链接的图像,请尝试this gallery link


是否有人知道如何使用包含自定义组件的 Scene Builder 加载 fxml 文件,该组件通过 java 代码动态添加子组件并修改其(或其)属性值而不在 fxml 中指定它们?

【问题讨论】:

  • 您使用哪个场景构建器?
  • 我尝试使用 1.0,但发现使用 1.1 可以! (见下面的答案)

标签: javafx-2 javafx custom-component fxml scenebuilder


【解决方案1】:

我找到了半年前的this post on oracle forum

据说这是一个错误,我发现在最新版本的场景构建器 (Scene Builder 1.1 Early Access) 中已修复。

使用此版本,一切正常。 :)

感谢您的帮助!

【讨论】:

  • 嗨,Daniel,如何在 Scene Builder 中打开调试模式?
  • 我认为 Scene Builder 中没有本机调试模式,我使用 Eclipse IDE 的远程调试功能做到了这一点。我执行了类似java -Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y -cp %CLASSPATH% com.oracle.javafx.authoring.Main 的操作,其中 CLASSPATH 设置为一个字符串,不包括 SceneBuilder 目录中的所有 jar + 我在此 FXML 文件中使用的我自己编译的类的目标目录。然后在 Eclipse IDE 中设置调试配置......也许你可以试试这个链接:sdqweb.ipd.kit.edu/wiki/Remote_Debugging_mit_Eclipse问候,Daniel
猜你喜欢
  • 1970-01-01
  • 2015-04-18
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2018-08-15
  • 1970-01-01
  • 2019-08-08
相关资源
最近更新 更多