首页 > 解决方案 > 绑定到 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 个示例),因此需要将属性封装在自定义类中.

标签: javafxconcurrencyinvocationtargetexception

解决方案


是的,此时 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。不知道我还能尝试什么?


推荐阅读