JavaFX 应用程序(使用预加载)过早退出

标签 java javafx preloader

我有一个使用预加载器初始化的 Java 应用程序。一旦 Preloader 隐藏,主应用程序启动并成功加载资源。然后应用程序窗口短暂加载然后退出,没有抛出任何异常。

主要应用代码:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.adrian.mobsters.gui;

import com.adrian.mobsters.resource.Resource;
import com.adrian.mobsters.resource.ResourceFactory;
import java.io.IOException;
import java.util.logging.Level;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.application.Preloader.ProgressNotification;
import javafx.application.Preloader.StateChangeNotification;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 *
 * @author aelder
 */
public class MainGUI extends Application {

    BooleanProperty ready = new SimpleBooleanProperty(false);

    public void loadResources() {
        Task task = new Task<Void>() {

            @Override
            protected Void call() throws Exception {
                java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
                System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog");

                double index = 0;
                for (ResourceFactory factory : ResourceFactory.values()) {
                    index++;
                    Resource resource = factory.getResource();

                    if (resource != null) {
                        resource.importResources();
                        notifyPreloader(new ProgressNotification(((double) index)/ResourceFactory.values().length));
                    }
                }

                ready.setValue(Boolean.TRUE);
                notifyPreloader(new StateChangeNotification(
                        StateChangeNotification.Type.BEFORE_START));
                return null;
            }
        };

        new Thread(task).start();
    }

    @Override
    public void start(Stage primaryStage) throws IOException {  
        loadResources();
        Parent root = FXMLLoader.load(MainGUI.class.getResource("main.fxml"));
        Scene scene = new Scene(root);

        primaryStage.setTitle("Mobsters Bot 2.0 - by Adrian Elder");
        primaryStage.setScene(scene);

        // After the app is ready, show the stage
        ready.addListener(new ChangeListener<Boolean>(){
            public void changed(
                ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                    if (Boolean.TRUE.equals(t1)) {
                        Platform.runLater(new Runnable() {
                            public void run() {
                                primaryStage.show();
                            }
                        });
                    }
                }
        });;  
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

预加载器代码:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package resourceloader;

import javafx.application.Preloader;
import javafx.application.Preloader.ProgressNotification;
import javafx.application.Preloader.StateChangeNotification;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * Simple Preloader Using the ProgressBar Control
 *
 * @author aelder
 */
public class ResourceLoader extends Preloader {

    ProgressBar bar;
    Stage stage;

    private Scene createPreloaderScene() {
        bar = new ProgressBar();
        BorderPane p = new BorderPane();
        p.setCenter(bar);
        return new Scene(p, 300, 150);      
    }

    @Override
    public void start(Stage stage) throws Exception {
        this.stage = stage;
        stage.setScene(createPreloaderScene());     
        stage.show();
    }

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

    @Override
    public void handleProgressNotification(ProgressNotification pn) {
        bar.setProgress(pn.getProgress());
    }   
}

更新: 好像跟在runLater方法中执行Stage show()方法有关系。由于某种原因,这会导致应用程序过早退出。

我目前的解决方案是 hibernate 直到资源加载完毕,然后在应用程序线程上执行 show 方法。

public void start(Stage primaryStage) throws IOException {
    this.primaryStage = primaryStage;

    primaryStage.setTitle("Mobsters Bot 2.0 - by Adrian Elder");
    primaryStage.getIcons().add(new Image(MainGUI.class.getResourceAsStream("/icons/sword.png")));

    currentThread = Thread.currentThread();
    primaryStage.setScene(new Scene(parent.get()));
    primaryStage.show();
}

@Override
public void init() throws InterruptedException {
    // After the app is ready, show the stage
    loadResources();

    while(!ready.get()) {
        Thread.sleep(100);
    }
}

最佳答案

将您的 primaryStage.show(); 移出事件并将其放在 primaryStage.setScene(scene); 之后,然后查看应用程序是否正常打开。我认为问题在于将其标记为就绪的事件

这对我有用。尝试注释记录器和资源,然后取消部分注释。这将有助于调试。由于我没有您的图书馆,所以我无法做进一步的事情。

public class Main extends Application {

    BooleanProperty ready = new SimpleBooleanProperty(false);

    public void loadResources() {
        Task task = new Task<Void>() {

            @Override
            protected Void call() throws Exception {
                //java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
                //System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog");

                /*double index = 0;
                for (ResourceFactory factory : ResourceFactory.values()) {
                    index++;
                    Resource resource = factory.getResource();

                    if (resource != null) {
                        resource.importResources();
                        notifyPreloader(new ProgressNotification(((double) index) / ResourceFactory.values().length));
                    }
                }*/

                ready.setValue(Boolean.TRUE);
                notifyPreloader(new StateChangeNotification(StateChangeNotification.Type.BEFORE_START));
                return null;
            }
        };

        new Thread(task).start();
    }

    @Override
    public void start(Stage primaryStage) throws IOException {

        //Parent root = FXMLLoader.load(Main.class.getResource("main.fxml"));
        Scene scene = new Scene(new Label("Application started"), 400, 400);

        primaryStage.setTitle("Mobsters Bot 2.0 - by Adrian Elder");
        primaryStage.setScene(scene);

        // After the app is ready, show the stage
        ready.addListener(new ChangeListener<Boolean>() {
            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (Boolean.TRUE.equals(t1)) {
                    Platform.runLater(new Runnable() {
                        public void run() {
                            primaryStage.show();
                        }
                    });
                }
            }
        });
        loadResources();
    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

关于JavaFX 应用程序(使用预加载)过早退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44087556/

相关文章:

java - 无法使用 ant 运行 GWTTestCase 测试

java - 在 Eclipse 中创建 JavaFX 自包含应用程序(使用自定义 JDK)

JavaFX:如何更改焦点遍历策略?

javascript - 制作 jquery windows.onload ,而不是等待图像

Java:来自unix时间戳的日期

java - 如果另一个映射中的键不存在,如何将元素添加到映射中

actionscript-3 - actionscript 3 中的预加载器 - getDefinition() 上的引用错误

javascript - 预加载器不会在加载时停止

java - "Insecure HTTP request is unsupported"Scala 错误

java - 如何使用 GeoTools 获取 shapeFile .shp 中多边形的所有点?