【问题标题】:Why does my JavaFX Preloader occasionally show up gray/black and other times it correctly loads?为什么我的 JavaFX 预加载器偶尔会显示为灰色/黑色,而有时它会正确加载?
【发布时间】:2017-10-12 12:57:52
【问题描述】:

我正在尝试让我的 JavaFX Preloader 启动屏幕显示在我的应用程序之前。我正在使用 Eclipse IDE,当我单击“运行”时,一半的时间启动画面会正确显示,而另一半的时间我会得到一个灰色或黑色的屏幕,而不是图像应该在的位置。

我不确定是什么问题导致它有时只能正确显示。

SplashController

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();
  }
}

然后在我的主课 Demo 中,我只有:

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 线程上有一个长时间运行的进程 :)
  • 好的,幸运的猜测:-),我刚刚将评论变成了答案。

标签: javafx preloader image-preloader


【解决方案1】:

很可能,您正在 JavaFX 应用程序线程或应用程序启动所涉及的线程上执行一些长时间运行的进程,这妨碍了预加载器的顺利运行。

我建议您查看Oracle Preloader sample 并与您的申请进行比较。确保您正确使用Task 等并发功能,类似于链接示例。检查链接的示例在您的环境中是否有效。

源代码(刚刚从 Oracle Preloader 示例链接复制)

请注意,在主 LongAppInit 应用程序类的 start 方法中,Task 和线程是如何产生的,以确保不会在 JavaFX 应用程序线程上进行长时间的应用程序启动。也可以看看应用程序的notifyPreloader()方法是如何在漫长的应用程序初始化过程中的不同时间调用的,让预加载器知道初始化过程的当前状态,从而在UI中实时准确的反映进度。

LongAppInitPreloader.java

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();
        }
    }  
 }

LongAppInit.java

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();
                            }
                        });
                    }
                }
        });;                
    }
}

【讨论】:

    猜你喜欢
    • 2021-07-11
    • 2021-04-05
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2015-05-10
    • 1970-01-01
    相关资源
    最近更新 更多