Load fxml as background process - Javafx

后端 未结 3 1196
滥情空心
滥情空心 2021-01-16 02:41

My initial fxml(say home.fxml) has a lot of functionalities, hence it takes a lot of time to load completely. So to avoid the time gap between program start and

3条回答
  •  星月不相逢
    2021-01-16 03:14

    Use a Task. You need to arrange to create the scene and update the stage on the FX Application Thread. The cleanest way is to use a Task:

    Task loadTask = new Task() {
        @Override
        public Parent call() throws IOException {
            FXMLLoader loader = new FXMLLoader();
            Parent root = loader.load(getClass().getResource("/uatreportgeneration/fxml/Home.fxml"));
            return root ;
        }
    };
    
    loadTask.setOnSucceeded(e -> {
        Scene scene = new Scene(loadTask.getValue());
    
        mainStage.setScene(scene);
        mainStage.show();
        stage.hide();
        System.out.println("Stage showing");
        // Get current screen of the stage
        ObservableList screens = Screen.getScreensForRectangle(new Rectangle2D(mainStage.getX(), mainStage.getY(), mainStage.getWidth(), mainStage.getHeight()));
        // Change stage properties
        Rectangle2D bounds = screens.get(0).getVisualBounds();
        mainStage.setX(bounds.getMinX());
        mainStage.setY(bounds.getMinY());
        mainStage.setWidth(bounds.getWidth());
        mainStage.setHeight(bounds.getHeight());
        System.out.println("thread complete");
    });
    
    loadTask.setOnFailed(e -> loadTask.getException().printStackTrace());
    
    Thread thread = new Thread(loadTask);
    thread.start();
    

    Here is a SSCCE using this technique:

    main.fxml:

    
    
    
    
    
    
    
    
        
            
        
        
        

    MainController (uses the Task approach shown above):

    import java.io.IOException;
    
    import javafx.concurrent.Task;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.stage.Stage;
    
    public class MainController {
        @FXML
        private Button button ;
        @FXML
        private void showWindow() {
            Task loadTask = new Task() {
                @Override
                public Parent call() throws IOException, InterruptedException {
    
                    // simulate long-loading process:
                    Thread.sleep(5000);
    
                    FXMLLoader loader = new FXMLLoader(getClass().getResource("test.fxml"));
                    Parent root = loader.load();
                    return root ;
                }
            };
    
            loadTask.setOnSucceeded(e -> {
                Scene scene = new Scene(loadTask.getValue());
                Stage stage = new Stage();
                stage.initOwner(button.getScene().getWindow());
                stage.setScene(scene);
                stage.show();
            });
    
            loadTask.setOnFailed(e -> loadTask.getException().printStackTrace());
    
            Thread thread = new Thread(loadTask);
            thread.start();
        }
    }
    

    test.fxml:

    
    
    
    
    
    
    
    
        
            
        
        

    TestController:

    import javafx.fxml.FXML;
    import javafx.scene.control.Label;
    
    public class TestController {
        @FXML
        private Label label ;
        @FXML
        private void closeWindow() {
            label.getScene().getWindow().hide();
        }
    }
    

    Main application:

    import java.io.IOException;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws IOException {
            primaryStage.setScene(new Scene(FXMLLoader.load(getClass().getResource("main.fxml"))));
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    Notice that after pressing the button, you can still type in the text field during the five seconds it takes to "load" the FXML, so the UI is remaining responsive.

提交回复
热议问题