如何从主应用程序的init()方法调用JavaFX应用程序预加载器示例中的方法

qcbq4gxm  于 2023-01-04  发布在  Java
关注(0)|答案(1)|浏览(165)

在JavaFX应用程序的init()方法中,我做了一些检查,其中之一是检查它是否可以使用Http响应代码连接到一个基于Web地址的应用程序。
根据响应代码,我希望它在预加载器应用程序的生命周期中显示一个警告窗口
我不确定使用当前的javafx预加载器类是否可以做到这一点,但是是否有任何变通方法可以实现这一点?
下面是我想要的SSCCE
应用程序

public class MainApplicationLauncher extends Application implements Initializable{

    ...

    public void init() throws Exception {       
          
        for (int i = 1; i <= COUNT_LIMIT; i++) {
            double progress =(double) i/10;
            System.out.println("progress: " +  progress);         
            
            notifyPreloader(new ProgressNotification(progress));
            Thread.sleep(500);
        }
        
        try {
            URL url = new URL("https://example.com");
            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();           
            int code = connection.getResponseCode();
            System.out.println("Response code of the object is "+code);
            if (code==200) {
                System.out.println("Connected to the internet!");
            }else if (code==503){
                        //call the handleConnectionWarning() in preloader
                System.out.println("server down !");
            }
        } catch (UnknownHostException e) {
                //call the handleConnectionWarning() in preloader
            System.out.println("cannot connect to the internet!");
        }

    public static void main(String[] args) {        
       System.setProperty("javafx.preloader", MainPreloader.class.getCanonicalName());
        Application.launch(MainApplicationLauncher.class, args);
   }
}

该预加载器

public class MyPreloader extends Preloader{

...

//Method that should be called from application method

public void handleConnectionWarning() {
        Alert alert = new Alert(AlertType.WARNING);
        alert.setTitle("Server is Offline");
        alert.setHeaderText("Cannot connect to service");
        alert.setContentText("Please check your connection");

        alert.showAndWait();
    }

}

有什么办法可以做到这一点吗?

svmlkihl

svmlkihl1#

预加载器

如果您想继续使用Preloader作为闪屏,那么您可以通过通知调用所需的方法。创建自己的通知类:

// You can modify this class to carry information to the Preloader, such
// as a message indicating what kind of failure occurred.
public class ConnectionFailedNotification implements Preloader.PreloaderNotification {}

发送到您的Preloader

notifyPreloader(new ConnectionFailedNotification());

并在上述Preloader中处理:

@Override
public void handleApplicationNotification(PreloaderNotification info) {
    if (info instanceof ConnectionFailedNotification) {
        handleConnectionWarning();
    }
    // ...
}

无预加载器

通过Java Web Start部署应用程序时,Preloader类更有意义(例如,到Web浏览器),其中代码必须在使用之前下载。但不再支持Java Web Start(尽管我认为可能有第三方维护至少类似的东西)。假设您的应用程序可能针对简单的桌面部署,使用Preloader可能会使事情变得不必要的复杂,而应考虑在初始化后简单地更新主阶段的内容。
将您的init()内容移动到Task实现中:

import java.io.IOException;
import javafx.concurrent.Task;

public class InitTask extends Task<Void> {

    private static final int COUNT_LIMIT = 10;

    private final boolean shouldSucceed;

    public InitTask(boolean shouldSucceed) {
        this.shouldSucceed = shouldSucceed;
    }

    @Override
    protected Void call() throws Exception {
        for (int i = 1; i <= COUNT_LIMIT; i++) {
            updateProgress(i, COUNT_LIMIT);
            Thread.sleep(500);
        }
        
        // could use a Boolean return type for this, but your real code seems
        // more complicated than a simple "yes" / "no" response. If you do
        // change the implementation to use a return value, note that you would
        // then need to check that return value in the 'onSucceeded' handler
        if (!shouldSucceed) {
            throw new IOException("service unavailable"); // failure
        }
        return null; // success
    }
    
}

然后在后台线程上启动该任务:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;;

public class App extends Application {
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        var task = new InitTask(false); // change to 'true' to simulate success
        task.setOnSucceeded(e -> primaryStage.getScene().setRoot(createMainScreen()));
        task.setOnFailed(e -> {
            var alert = new Alert(AlertType.WARNING);
            alert.initOwner(primaryStage);
            alert.setTitle("Server Offline");
            alert.setHeaderText("Cannot connect to service");
            alert.setContentText("Please check your connection");
            alert.showAndWait();

            Platform.exit();
        });

        // Also see the java.util.concurrent.Executor framework
        var thread = new Thread(task, "init-thread");
        thread.setDaemon(true);
        thread.start();

        var scene = new Scene(createSplashScreen(task), 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private StackPane createSplashScreen(InitTask task) {
        var bar = new ProgressBar();
        bar.progressProperty().bind(task.progressProperty());
        return new StackPane(bar);
    }

    private StackPane createMainScreen() {
        return new StackPane(new Label("Hello, World!"));
    }
}

旁注

Application子类不应实现Initializable。该子类表示整个应用程序,并且绝不应用作FXML控制器。

相关问题