Почему мой предварительный загрузчик JavaFX иногда отображается серым/черным цветом, а в других случаях загружается правильно?

Я пытаюсь, чтобы мой экран-заставка JavaFX Preloader отображался перед моим приложением. Я использую Eclipse IDE, и когда я нажимаю «Выполнить», в половине случаев экран-заставка будет отображаться правильно, а в другой половине времени я получаю серый или черный экран вместо того, где должно быть изображение.

Я не уверен, в чем проблема, чтобы иногда он отображался правильно.

Контроллер заставки:

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

}


person chip    schedule 12.10.2017    source источник
comment
Благодарю вас! Да, проблема была в том, что у меня был длительный процесс в потоке JavaFX :)   -  person chip    schedule 12.10.2017
comment
Хорошо, удачная догадка :-), я только что превратил комментарий в ответ.   -  person jewelsea    schedule 12.10.2017


Ответы (1)


Скорее всего, вы выполняете какой-то длительный процесс в потоке приложения JavaFX или в потоке, участвующем в запуске приложения, что препятствует бесперебойной работе предварительного загрузчика.

Я предлагаю вам просмотреть пример Oracle Preloader и сравните с вашим приложением. Убедитесь, что вы используете параллельные функции, такие как Task правильно, аналогично приведенному примеру. Убедитесь, что связанный пример работает в вашей среде.

Исходный код (только что скопирован из примера ссылки Oracle Preloader)

Обратите внимание, что в методе запуска основного LongAppInit класса приложения Task и создается поток, чтобы гарантировать, что длительное инициирование приложения не происходит в потоке приложения JavaFX. Также посмотрите, как notifyPreloader() метод приложения вызывается в разное время в течение длительной инициализации приложения, чтобы сообщить загрузчику о текущем состоянии процесса инициализации, чтобы он мог точно отображать ход выполнения в пользовательском интерфейсе в режиме реального времени.

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();
                            }
                        });
                    }
                }
        });;                
    }
}
person jewelsea    schedule 12.10.2017