如何在 JavaFx 中为自定义组件创建属性?
How to create an attribute for a custom component in JavaFx?
经过几个小时的工作,我设法了解了如何使用 javafx 和 Gluons Scene Builder 创建自定义组件。
如何为将出现在场景构建器属性菜单中的组件添加一个新的 属性,以便可以在设计时输入 属性 值。
您需要子class 某些东西,很可能是 Parent
、Region
或 Pane
的实现。从那里你可以加载由你在 Scene Builder
.
中所做的任何事情生成的 FXML
示例:
public class MyComponent extends VBox {
private final StringProperty foo = new SimpleStringProperty();
public MyComponent {
final Parent root = (Parent) FXMLLoader.load(getClass().getResource(fxmlPath));
getChildren().add(root);
}
public final StringProperty fooProperty() { return foo; }
public final String getFoo() { return foo.get(); }
public final void setFoo(String foo) { this.foo.set(foo); }
}
这可能会产生一个额外的容器,一个是MyComponent
,另一个是FXML 的根节点。为防止这种情况,请使用 FXMLLoader.setRoot()
.
更新
看来你有一个额外的障碍-具有主要逻辑的控制器与MyComponent
解耦。
有很多方法可以做到这一点:
通过引用传递
您可以将MyComponent
的引用传入控制器。
public class MyController {
/* Your controller stuff */
private MyComponent component;
public final void setComponent(MyComponent component) {
// You can bind your controller properties to fooProperty here
}
}
然后在MyComponent
中加载FXML时,获取控制器的引用并手动调用setComponent()
。
通过公开控制器 属性
该方法直接暴露了MyComponent
中控制器的属性
public class MyComponent extends VBox {
// Other stuff
private MyController controller;
public MyComponent {
// Original stuff
this.controller = loader.getController();
}
public final StringProperty fooProperty() {
assert controller != null; // If you loaded correctly this assertion should be valid
return controller.fooProperty();
}
public final String getFoo() { return fooProperty().get(); }
public final void setFoo(String foo) { fooProperty().set(foo); }
}
将控制器集成到组件中
此方法只是将 MyComponent
和 MyController
合并为一个 class。你需要 FXMLLoader.setController(this)
.
优点是您可以直接访问所有内容。不好的是,有些人会说这违反了 MVC。
经过几个小时的工作,我设法了解了如何使用 javafx 和 Gluons Scene Builder 创建自定义组件。 如何为将出现在场景构建器属性菜单中的组件添加一个新的 属性,以便可以在设计时输入 属性 值。
您需要子class 某些东西,很可能是 Parent
、Region
或 Pane
的实现。从那里你可以加载由你在 Scene Builder
.
示例:
public class MyComponent extends VBox {
private final StringProperty foo = new SimpleStringProperty();
public MyComponent {
final Parent root = (Parent) FXMLLoader.load(getClass().getResource(fxmlPath));
getChildren().add(root);
}
public final StringProperty fooProperty() { return foo; }
public final String getFoo() { return foo.get(); }
public final void setFoo(String foo) { this.foo.set(foo); }
}
这可能会产生一个额外的容器,一个是MyComponent
,另一个是FXML 的根节点。为防止这种情况,请使用 FXMLLoader.setRoot()
.
更新
看来你有一个额外的障碍-具有主要逻辑的控制器与MyComponent
解耦。
有很多方法可以做到这一点:
通过引用传递
您可以将MyComponent
的引用传入控制器。
public class MyController {
/* Your controller stuff */
private MyComponent component;
public final void setComponent(MyComponent component) {
// You can bind your controller properties to fooProperty here
}
}
然后在MyComponent
中加载FXML时,获取控制器的引用并手动调用setComponent()
。
通过公开控制器 属性
该方法直接暴露了MyComponent
中控制器的属性
public class MyComponent extends VBox {
// Other stuff
private MyController controller;
public MyComponent {
// Original stuff
this.controller = loader.getController();
}
public final StringProperty fooProperty() {
assert controller != null; // If you loaded correctly this assertion should be valid
return controller.fooProperty();
}
public final String getFoo() { return fooProperty().get(); }
public final void setFoo(String foo) { fooProperty().set(foo); }
}
将控制器集成到组件中
此方法只是将 MyComponent
和 MyController
合并为一个 class。你需要 FXMLLoader.setController(this)
.
优点是您可以直接访问所有内容。不好的是,有些人会说这违反了 MVC。