简体   繁体   English

JavaFX-任务的新阶段

[英]JavaFX- new Stage in a task

I want to open a new window from the task but for some reason after line Stage stage = new Stage the code stops executing, but there is no error. 我想从任务中打开一个新窗口,但是由于某些原因,在Stage stage = new Stage行之后,代码停止执行,但是没有错误。

Task<Void> task = new Task<Void>() {

        @Override protected Void call() throws Exception {

            Parent root = FXMLLoader.load(getClass().getResource("sample2.fxml"));
            Stage stage = new Stage();
            System.out.println("Print");
            stage.setTitle("My New Stage Title");
            stage.setScene(new Scene(root, 100, 100));
            stage.show();
            return null;
        }
    };

It never prints out the message 'Print'. 它从不打印出“打印”消息。

Answer to Question 回答问题

The reason your Task is failing is because you are creating a Stage on a thread other than the JavaFX Application Thread. Task失败的原因是因为您正在JavaFX Application Thread之外的其他线程上创建Stage The Javadoc of Stage states: Stage的Javadoc指出:

Stage objects must be constructed and modified on the JavaFX Application Thread. 舞台对象必须在JavaFX Application Thread上构造和修改。

This means when you attempt to create a Stage on the background thread that the Task is running on it will result in an IllegalStateException with a message telling you that you aren't on the JavaFX Application Thread. 这意味着,当您尝试在正在其上运行Task的后台线程上创建一个Stage时,将导致IllegalStateException并显示一条消息,告知您不在JavaFX Application Thread上。 To solve this issue wrap all code that creates and/or modifies a Stage in a Platform.runLater(Runnable) call. 要解决此问题,请在Platform.runLater(Runnable)调用中包装所有创建和/或修改Stage代码。

Side Note: It would probably be better to not create the Stage in the Task at all. 旁注:最好根本不在Task中创建Stage Rather, in your case, simply return the result of FXMLLoader.load(URL) and create the Stage when handling the success of the Task . 相反,在您的情况下,仅在处理Task成功时返回FXMLLoader.load(URL)的结果并创建Stage

Task<Parent> task = new Task<Parent>() {
    @Override
    protected Parent call() throws Exception {
        return FXMLLoader.load(getClass().getResource("sample2.fxml"));
    }
};

task.setOnSucceeded(event -> {
    Parent root = task.getValue();
    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.show();
};

Why No Error Shown? 为什么没有显示错误?

You say there is no error but you also don't show any code that would display an error if one does occurr. 您说没有错误,但是您也不会显示任何代码,如果发生的话会显示错误。 When a Task fails it sets the cause of failure in the exception property. Task失败时,它将在exception属性中设置失败的原因。 To handle the case when a Task fails you can: 要处理Task失败时的情况,您可以:

  • Listen to the exception property exception属性
  • Add an EventHandler to handle a WorkerStateEvent.WORKER_STATE_FAILED event and query the exception property 添加一个EventHandler来处理WorkerStateEvent.WORKER_STATE_FAILED事件并查询exception属性
    • Either using task.setOnFailed(EventHandler) or task.addEventXXX(EventType, EventHandler) where XXX is either Filter or Handler 使用task.setOnFailed(EventHandler)task.addEventXXX(EventType, EventHandler) ,其中XXXFilterHandler
  • Override the protected void failed() method in your Task implementation and query the exception property 覆盖Task实现中protected void failed()方法,并查询exception属性
    • The failed() method will always be called on the JavaFX Application Thread failed()方法将始终在JavaFX Application Thread上调用
  • Catch and handle the exception in the call() method before re-throwing it 在重新抛出异常之前,在call()方法中捕获并处理异常
  • Possibly other ways I'm not currently thinking of 我目前未想到的其他方式

You need an Executor to start the thread 您需要一个执行程序来启动线程

Executor exec = Executors.newCachedThreadPool(runnable -> {
    Thread t = new Thread(runnable);
    t.setDaemon(true);
    return t;
});

exec.execute(task);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM