【发布时间】:2021-06-01 13:54:01
【问题描述】:
我正在尝试将自定义控件添加到我在此处找到的示例中:https://spring.io/blog/2019/01/16/spring-tips-javafx (代码:https://github.com/ecovaci/javafx-spring-boot/tree/master)
我的目标当然是能够在我的控制器中自动装配业务服务:
@Service
public class TestService {
public void test() {
System.out.println("test");
}
}
我可以通过非自定义控件中的构造函数注入来做到这一点:
@Component
public class SimpleUiController {
private final HostServices hostServices;
@FXML
public Label label;
@FXML
public Button button;
private TestService testService;
public SimpleUiController(HostServices hostServices, TestService testService) {
Assert.notNull(testService);
this.hostServices = hostServices;
this.testService = testService;
}
@FXML
public void initialize () {
this.button.setOnAction(actionEvent -> this.testService.test());
}
}
接下来我想在 fxml 中添加一个自定义控件,并附带一个控制器。 所以我天真地复制了这里找到的代码 sn-ps:https://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
<!-- custom_control.fxml -->
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
<TextField fx:id="textField"/>
<Button text="Click Me" />
</fx:root>
@Component
public class CustomControl extends VBox {
@FXML
private TextField textField;
private TestService testService;
public CustomControl(TestService testService) {
Assert.notNull(testService);
this.testService = testService;
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/custom_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public String getText() {
return textProperty().get();
}
public void setText(String value) {
textProperty().set(value);
}
public StringProperty textProperty() {
return textField.textProperty();
}
}
现在我可以像这样使用我的自定义控件了:
<!--ui.fxml-->
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.example.javafx.SimpleUiController">
<Button fx:id="button" text="Button" />
<Label fx:id="label" text="Label" />
<CustomControl text="100"/>
</VBox>
但是当我添加自定义控件时,出现以下异常。
Exception in Application start method
Caused by: java.lang.NoSuchMethodException: com.example.javafx.CustomControl.<init>()
我对 JavaFx 比较陌生,很高兴能找到一些关于与 Spring 集成的文章。但是我没有找到任何关于自定义控件和弹簧的参考资料。几乎感觉就像我是唯一一个试图实现这一目标的人,我错过了什么吗?
【问题讨论】:
-
当您在 FXML 文件中包含这样的自定义控件时会发生什么,
FXMLLoader通过反射实例化控件,调用(默认情况下)无参数构造函数。您需要安排FXMLLoader从spring 应用程序上下文中检索控件的实例。我认为这样做的方法是在FXMLLoader上使用自定义builder factory。 -
我认为如果无法从 Spring 获得对象,则(已删除)答案中的代码问题是返回 null。 (所以我怀疑它在 FXML 中的
Button和Label上失败,而不是在自定义控件上。在您的自定义构建器工厂中创建一个JavaFxBuilderFactory,如果没有合格则返回getBuilder()的结果豆子。 -
我也遇到了以下错误:属性“文本”不存在或者是只读的。由于我正在创建的构建器不会从我的 bean 中公开我的 getter 和 setter。您是否也有针对 @James_D 的优雅解决方案? ;o)
-
我认为这只是将您的包打开到
javafx.fxml以便它可以使用反射的情况,但我不确定。
标签: java spring javafx dependency-injection