javafx - 绑定到 JavaFX 并发任务运行的自定义类时出现 InvocationTargetException
问题描述
尝试绑定到由 Task 运行的自定义类时,我收到 InvocationTargetException 和 NullPointerException。我有绑定到库类 ObeservableList、Long、Integer 等的工作示例,但现在需要绑定到自定义类的值。我为绑定目的创建了包含 StringProperty 的 TaskOutput 类,如下所示:
public class TaskOutput {
private final StringProperty textValue = new SimpleStringProperty();
public TaskOutput(String textValue) {
this.textValue.set(textValue);
}
public String getTextValue() {
return textValue.get();
}
public void setTextValue(String textValue) {
this.textValue.set(textValue);
}
public final StringProperty nameProperty() {
return this.textValue;
}
}
这已成功测试如下:
TaskOutput newTaskOutput = new TaskOutput("Text of TaskOutput");
value.textProperty().bind(newTaskOutput.nameProperty());
System.out.println(value.getText());
现在我正在尝试运行一个提供 TaskOutput 作为其值属性的任务。扩展Task的类如下:
public class NameGeneratorTask extends Task<TaskOutput> {
private int counter;
TaskOutput taskOutput;
public NameGeneratorTask() {
this.counter = 10;
taskOutput = new TaskOutput("Test String from output");
}
@Override
protected TaskOutput call() {
this.updateTitle("Name Generator");
do {
if (this.isCancelled())
{
break;
}
updateValue(taskOutput);
counter--;
}
while (counter > 0);
return taskOutput;
}
}
Application 类实例化一个 Task 对象,然后将其传递给 WorkerState 类,如下所示:
public class FxConcurrentBespokeObjectVersion2 extends Application
{
NameGeneratorTask task;
public static void main(String[] args)
{
Application.launch(args);
}
@Override
public void start(final Stage stage)
{
task = new NameGeneratorTask();
WorkerState pane = new WorkerState(task);
}
}
WorkerState 类尝试绑定到由 Task 运行的 TaskOutput 的 nameProperty,如下所示:
public class WorkerState
{
private final TextArea value = new TextArea("");
public WorkerState(Worker<TaskOutput> worker)
{
value.textProperty().bind(worker.valueProperty().get().nameProperty());
}
}
此时程序编译,但在运行时生成此异常:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.NullPointerException
at OriginalExBespokeObjectVersion2.WorkerState.<init>(WorkerState.java:21)
at OriginalExBespokeObjectVersion2.FxConcurrentBespokeObjectVersion2.start(FxConcurrentBespokeObjectVersion2.java:29)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
... 1 more
Exception running application OriginalExBespokeObjectVersion2.FxConcurrentBespokeObjectVersion2
正如我所提到的,我已经设法绑定到库类,所以不明白为什么我不能在同一场景中绑定到我的自定义类(尽管我可以在上面的独立示例中很好地绑定到它)。有人可以建议吗?如果有人想知道,“为什么不使用任务(字符串)?”...我的程序的目标是从同一个任务返回多个属性(字符串只是 1 个示例),因此需要将属性封装在自定义类中.
解决方案
是的,此时 worker.valueProperty() 和 worker.valueProperty().get() 都返回 null。早些时候我试过这个:
value.textProperty().bind(
new When(worker.valueProperty().isNull()).then("Unknown")
.otherwise(worker.valueProperty().get().nameProperty()));
……但结果是一样的。它知道为 null 是一个问题,但是当我设法与 Long 之类的库类型很好地绑定时,我看不出它与以前有何不同。在这种情况下,这条线工作得很好: value.textProperty().bind(worker.valueProperty().asString()); 我检查并在属性类型为 Long worker.valueProperty() 的情况下在绑定时也为空,这不是问题。
更新:
我检查了工作示例中使用的 worker.valueProperty().asString() 并看到它正在返回 StringBinding 所以我修改了我的自定义类以执行以下相同操作:
public class TaskOutput {
private final String textValue = new String("Start value");
public TaskOutput() {
}
public StringBinding getStringBinding() {
return new StringBinding() {
@Override
protected String computeValue() {
return textValue;
}
};
}
}
我已将其部署在 WorkerState 类中,如下所示:
value.textProperty().bind(worker.valueProperty().get().getStringBinding());
但仍然是相同的结果,InvocationTargetException 和 Runtime Exception。不知道我还能尝试什么?
推荐阅读
- vim - 我不明白为什么 Vim 脚本中的 job_start 会发生这样的事情?
- css - 与父级分隔容器宽度
- javascript - Laravel REST API 何时为值列表创建单独的控制器?
- java - Stream.forEach() 中的 `return;` 将控制中断到哪里?
- r - glmer() 以一个因子水平作为基线收敛,但在将基线重新调整到另一个水平时无法收敛
- java - Spring Boot MVC - 不支持请求方法“POST”
- python - 在生成梯度下降函数和成本方面需要帮助
- ios - 每次我尝试构建应用程序时,nodemediaclient 都会收到此错误,反应原生 IOS
- parameters - 为什么以及何时我要在 Lua 中使用 os.exit() 函数的参数“代码”
- azure - 微软 Azure 笔记本