JavaFX Preloader Thread [英] JavaFX Preloader Thread

查看:220
本文介绍了JavaFX Preloader Thread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有人解释一下Preloader在JavaFX应用程序中的工作原理。我已经发现了生命周期,我知道首先调用preloader的start(..)然后启动(..)Application,但是这两个方法是从同一个Thread调用的吗?我试图在应用程序的启动方法中创建一个简单的应用程序,放入Thread.sleep(8000),并在Preloader的开头我创建了一个简单的阶段并显示它。但是当我运行应用程序时,它只是在黑色阶段冻结,并且仅在8秒后正确显示预加载器阶段,但为什么?

I need someone explain me how Preloader works in JavaFX application. I have already found out the lifecycle and I know that first is called start(..) of preloader and then start(..) of Application but is this two methods are called from the same Thread? I have tried to make a simple app in start method of application a put Thread.sleep(8000) and in the start of Preloader I created a simple stage and show it. But when I run the application it just freeze with black stage and only after 8 seconds shows preloader stage correctly, but why?

使用源代码更新我的帖子:

公共类PreloaderApp扩展Preloader {

public class PreloaderApp extends Preloader {

public void init(){
    System.out.println("Thread Preloader ID:"+ Thread.currentThread().getId());
    System.out.println("  ------  ");

    Pane effectRegion = LoaderFrame.getInstance().getEffectPane();
    JFXFillTransition fill = new JFXFillTransition();
    fill.setDuration(Duration.millis(400));
    fill.setRegion(effectRegion);
    fill.setAutoReverse(true);
    fill.setCycleCount(Animation.INDEFINITE);
    fill.setFromValue(Color.WHITE);
    fill.setToValue(Color.rgb(0,77,147));

    fill.play();

}

@Override
public void start(Stage primaryStage){
    System.out.println("Thread Preloader(start) ID:"+ Thread.currentThread().getId());
    System.out.println("  ------  ");
    LoaderFrame.getInstance().show();

}

}

public class LoaderFrame extends Stage {

私有静态final LoaderFrame instance = new LoaderFrame();

private static final LoaderFrame instance = new LoaderFrame();

public static LoaderFrame getInstance(){
    return instance;
}


private Scene scene;
private AnchorPane root;
private BorderPane wraper;
private StackPane effectPane;

private JFXButton loaderPathButton;


public LoaderFrame(){
    initScene();
    this.initStyle(StageStyle.TRANSPARENT);
    this.getIcons().add(new Image("file:imgs/favico/icon48.png"));
}

public void initScene(){
    FXMLLoader loader = new FXMLLoader(Main.class.getResource("xml/loader_frame.fxml"));
    root = null;

    try {
        root = loader.load();
        wraper = (BorderPane) root.lookup("#rootPane");
        loaderPathButton = (JFXButton) root.lookup("#loaderPathButton");
        effectPane = (StackPane) root.lookup("#effectPane");
        scene = new Scene(root);
        scene.setFill(Color.TRANSPARENT);
        scene.getStylesheets().add("file:css/loader.css");
        this.setScene(scene);
    } catch (IOException e) {
        e.printStackTrace();
    }

}


public Pane getEffectPane(){
    return effectPane;
}

}

推荐答案

要调查预加载器生命周期,您可以将以下行添加到预加载器 class:

To investigate the Preloader lifecycle you could add the following line to your Preloader class:

    @Override
    public void handleStateChangeNotification(StateChangeNotification info) {
        System.out.println("state: " + info.getType());
    }

应用程序中您可以在 init / start中添加 System.out.prinln 消息code>方法。这将显示 Preloader 在其不同状态下运行: BEFORE_LOAD BEFORE_INIT BEFORE_START

In your Application class you can add a System.out.prinln message in the init / start method. This will show the Preloader running through its different states: BEFORE_LOAD, BEFORE_INIT, BEFORE_START.

由于预加载器启动方法 JavaFXThread 上调用你必须在中将你的调用包装到 Thread.sleep Platform.runlater

As the Preloaders start method is called on the JavaFXThread you have to wrap your call to Thread.sleep in Platform.runlater.


请注意,预加载器遵循与其他JavaFX应用程序相同的规则,包括FX线程规则。特别是,类构造函数和init()方法将在非FX线程上调用,start()将在FX应用程序线程上执行。这也意味着应用程序构造函数/ init()将与preloader start()同时运行。

Note that preloaders are subject to the same rules as other JavaFX applications including FX threading rules. In particular, the class constructor and init() method will be called on a non-FX thread and start() will be executed on the FX application thread. This also means that the application constructor/init() will run concurrently with preloader start().

如果你需要花一些时间进行初始化,你应该在你的应用程序中执行 init 方法。当预加载器状态更改为 BEFORE_START 时,您可以隐藏预加载器阶段

If you need to do some time consuming initialization, you should do it in your Apps init method. When the Preloader state changes to BEFORE_START you can hide your Preloader stage

public class App extends Application {

    private static final int PRELOADER_SHOWTIME_MILLIS = 2000;

    @Override
    public void init() throws Exception {
        long start = System.currentTimeMillis();

        // time consuming initializations

        long duration = System.currentTimeMillis() - start;
        long remainingShowTime = PRELOADER_SHOWTIME_MILLIS - duration;

        if(remaingShowTime > 0 ){
            Thread.sleep(remainingShowTime);
        }
    }

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane(new Label("application"));
        Scene scene = new Scene(root, 400, 400);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

public class TestPreloader extends Preloader {

    private Stage stage;  

    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;

        Rectangle rect = new Rectangle(200, 200, Color.RED);
        FadeTransition transition = new FadeTransition(Duration.seconds(2), rect);
        transition.setFromValue(0);
        transition.setToValue(1);

        Label lbl = new Label("preloader");
        StackPane root = new StackPane(rect, lbl);

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        transition.play();
    }

    @Override
    public void handleStateChangeNotification(StateChangeNotification info) {
        if (info.getType() == Type.BEFORE_START) {
           stage.hide();
        }
     }

}

public class Main {

    public static void main(String[] args) {
        LauncherImpl.launchApplication(App.class, TestPreloader.class, args);
    }

}

这篇关于JavaFX Preloader Thread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆