JavaFX应用程序(使用预加载)过早退出
问题描述:
我有一个使用Preloader进行初始化的Java应用程序。 Preloader隐藏后,主应用程序启动并成功加载资源。应用程序窗口然后暂时加载,然后退出,没有抛出异常。JavaFX应用程序(使用预加载)过早退出
主要应用代码:
/*
* 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());
}
}
更新: 看来它是与执行阶段show()方法的runLater方法。出于某种原因,这会导致应用程序过早退出。
我现在的解决方案是睡觉,直到资源被加载,然后在应用程序线程上执行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);
}
}
解决了这个问题,但不会允许应用程序在资源完成加载之前启动?我按照oracle的教程(图13-12)(http://docs.oracle.com/javase/8/docs/technotes/guides/deploy/preloaders.html#BABGGDJG)来使用这个事件模式。 –
我觉得问题出在你保护的Void调用()抛出异常 函数。你调试了吗?我想在该函数中添加一个try catch,并且你应该得到一个错误。我无法调试您的代码,因为引用了一些我没有的库 –
即使删除我的所有本地代码,错误仍然会发生。删除除了将进度栏通知更新为1.0之外的所有代码。 –