我编写了一个 FXML 文件,其中使用了一个自定义组件,扩展了 Group。
当加载这个自定义组件时,它应该添加一些 child (这里:MyOverlayIcon)到它的 children-list 并通过代码设置一些属性(这里:layoutX 和 layoutY)。
我的图标.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 文件 fith FXMLLoader,它工作正常:添加并正确显示所有新子项:
现在我想用 Scene Builder 修改这个 fxml 文件。
但是当我使用 Scene Builder 加载文件时,我只看到一个空的组实例:
我发现只有这两种解决方法:
1.) 调用将子项显式添加到子项列表的方法(例如在属性的 setter-method 内),子项被添加和显示,但仅在通过修改某些内容而不是在开始时调用此 setter 时文件已加载。
2.) 在 Debug模式下运行 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 中指定它们?
最佳答案
我找到了 this post on oracle forum从半年前开始。
据说,这是一个错误,我发现在最新版本的场景构建器( Scene Builder 1.1 Early Access )中已修复。
使用此版本,一切正常。 :)
谢谢你的帮助!
关于javafx-2 - 在 JavaFX Scene Builder : Attributes are reset and children removed 中加载带有自定义组件的 FXML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15905204/