为什么我的JavaFX预加载程序偶尔会显示为灰色/黑色,而其他时候它会正确加载?
我正试图让我的JavaFX预加载程序启动屏幕在我的应用程序之前显示出来。我使用的是EclipseIDE,当我单击“运行”时,一半时间启动屏幕将正确显示,另一半时间我将看到灰色或黑色屏幕,而不是图像应该显示的位置 我不确定是什么问题导致它有时只能正确显示 飞溅控制器:为什么我的JavaFX预加载程序偶尔会显示为灰色/黑色,而其他时候它会正确加载?,javafx,preloader,image-preloader,Javafx,Preloader,Image Preloader,我正试图让我的JavaFX预加载程序启动屏幕在我的应用程序之前显示出来。我使用的是EclipseIDE,当我单击“运行”时,一半时间启动屏幕将正确显示,另一半时间我将看到灰色或黑色屏幕,而不是图像应该显示的位置 我不确定是什么问题导致它有时只能正确显示 飞溅控制器: public class SplashController extends Preloader { private static final double WIDTH = 676; private static final
public class SplashController extends Preloader {
private static final double WIDTH = 676;
private static final double HEIGHT = 227;
private Stage preloaderStage;
private Label progressText;
private Pane splashScreen;
public SplashController() {}
@Override
public void init() throws Exception {
ImageView splash =
new ImageView(new Image(Demo.class.getResource("pic.png").toString()));
progressText =
new Label("VERSION: " + getVersion() + " ~~~ Loading plugins, please wait...");
splashScreen = new VBox();
splashScreen.getChildren().addAll(splash, progressText);
progressText.setAlignment(Pos.CENTER);
}
@Override
public void start(Stage primaryStage) throws Exception {
this.preloaderStage = primaryStage;
Scene splashScene = new Scene(splashScreen);
this.preloaderStage.initStyle(StageStyle.UNDECORATED);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
this.preloaderStage.setScene(splashScene);
this.preloaderStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - WIDTH / 2);
this.preloaderStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - HEIGHT / 2);
this.preloaderStage.show();
}
}
然后在我的主课演示中我只需要:
public class Demo extends Application {
@Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new
FXMLLoader(Demo.class.getResource("FXMLDocument.fxml"));
GridPane root = loader.load();
--------other app code here---------
}
public static void main(String[] args) {
LauncherImpl.launchApplication(Demo.class, SplashController.class, args);
}
}很可能,您正在JavaFX应用程序线程或应用程序启动所涉及的线程上执行一些长时间运行的进程,这会妨碍预加载程序的顺利运行 我建议你审查一份申请,并与你的申请进行比较。确保您正确使用了与链接示例类似的并发功能,如。检查链接的示例是否在您的环境中工作 源代码(刚从Oracle预加载程序示例链接复制) 请注意,在main
LongAppInit
应用程序类的start方法中,如何生成and线程,以确保长应用程序启动不会发生在JavaFX应用程序线程上。还可以看到在长时间的应用程序初始化过程中,如何在不同的时间调用application方法,以让预加载程序知道初始化过程的当前状态,从而使其能够实时准确地反映UI中的进度
longappinitpreload.java
LongAppInit.java
公共类LongInitApp扩展应用程序{
阶段性;
BooleanProperty ready=新的SimpleBoleanProperty(false);
私有void longStart(){
//在后台模拟长初始化
任务=新任务(){
@凌驾
受保护的Void调用()引发异常{
int max=10;
对于(int i=1;i可能,您正在JavaFX应用程序线程或应用程序启动所涉及的线程上执行一些长时间运行的进程,这会妨碍预加载程序的顺利运行
我建议您查看并与您的应用程序进行比较。确保您正确使用了与链接示例类似的并发功能。检查链接示例在您的环境中是否有效
源代码(刚从Oracle预加载程序示例链接复制)
请注意,在主LongAppInit
应用程序类的start方法中,如何生成and线程,以确保长应用程序启动不会发生在JavaFX应用程序线程上。还可以查看如何在长应用程序初始化中的不同时间调用application方法,以允许预加载r了解初始化过程的当前状态,以便能够在UI中实时准确地反映进度
longappinitpreload.java
LongAppInit.java
公共类LongInitApp扩展应用程序{
阶段性;
BooleanProperty ready=新的SimpleBoleanProperty(false);
私有void longStart(){
//在后台模拟长初始化
任务=新任务(){
@凌驾
受保护的Void调用()引发异常{
int max=10;
对于(int i=1;我感谢你!是的,问题是我在JavaFX线程上有一个长时间运行的进程:)好的,幸运的猜测:-),我只是把评论做成了一个答案。谢谢你!是的,问题是我在JavaFX线程上有一个长时间运行的进程:)好的,幸运的猜测:-),我只是把评论做成了一个答案。
public class LongAppInitPreloader extends Preloader {
ProgressBar bar;
Stage stage;
boolean noLoadingProgress = true;
private Scene createPreloaderScene() {
bar = new ProgressBar(0);
BorderPane p = new BorderPane();
p.setCenter(bar);
return new Scene(p, 300, 150);
}
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setScene(createPreloaderScene());
stage.show();
}
@Override
public void handleProgressNotification(ProgressNotification pn) {
//application loading progress is rescaled to be first 50%
//Even if there is nothing to load 0% and 100% events can be
// delivered
if (pn.getProgress() != 1.0 || !noLoadingProgress) {
bar.setProgress(pn.getProgress()/2);
if (pn.getProgress() > 0) {
noLoadingProgress = false;
}
}
}
@Override
public void handleStateChangeNotification(StateChangeNotification evt) {
//ignore, hide after application signals it is ready
}
@Override
public void handleApplicationNotification(PreloaderNotification pn) {
if (pn instanceof ProgressNotification) {
//expect application to send us progress notifications
//with progress ranging from 0 to 1.0
double v = ((ProgressNotification) pn).getProgress();
if (!noLoadingProgress) {
//if we were receiving loading progress notifications
//then progress is already at 50%.
//Rescale application progress to start from 50%
v = 0.5 + v/2;
}
bar.setProgress(v);
} else if (pn instanceof StateChangeNotification) {
//hide after get any state update from application
stage.hide();
}
}
}
public class LongInitApp extends Application {
Stage stage;
BooleanProperty ready = new SimpleBooleanProperty(false);
private void longStart() {
//simulate long init in background
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
int max = 10;
for (int i = 1; i <= max; i++) {
Thread.sleep(200);
// Send progress to preloader
notifyPreloader(new ProgressNotification(((double) i)/max));
}
// After init is ready, the app is ready to be shown
// Do this before hiding the preloader stage to prevent the
// app from exiting prematurely
ready.setValue(Boolean.TRUE);
notifyPreloader(new StateChangeNotification(
StateChangeNotification.Type.BEFORE_START));
return null;
}
};
new Thread(task).start();
}
@Override
public void start(final Stage stage) throws Exception {
// Initiate simulated long startup sequence
longStart();
stage.setScene(new Scene(new Label("Application started"),
400, 400));
// 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() {
stage.show();
}
});
}
}
});;
}
}