为什么我的JavaFX预加载器偶尔会显示灰色/黑色和其他正确加载的时间?

问题描述:

我试图让我的JavaFX Preloader飞溅屏幕出现在我的应用程序之前。我使用的是Eclipse IDE,当我点击“运行”时,一半的时间启动屏幕将正确显示,另一半时间我会得到一个灰色或黑色的屏幕,而不是图像应该在哪里。为什么我的JavaFX预加载器偶尔会显示灰色/黑色和其他正确加载的时间?

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

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

然后在我的主类演示我只是有:

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

}

+0

谢谢!是的,问题是我在JavaFX线程上有一个长时间运行的过程:) – chip

+0

好的,幸运的猜测:-),我只是把评论做成了一个答案。 – jewelsea

可能的是,你正在执行一些在长时间运行的进程JavaFX应用程序线程或应用程序启动中涉及的线程,其中阻止预加载器的平稳运行。

我建议您检查Oracle Preloader sample并与您的应用程序进行比较。确保您正确使用Task等并发功能,与链接示例类似。检查环境中的链接示例作品。

源代码(从Oracle预载样品链接只是复制)

注意如何在主LongAppInit应用程序类的启动方法,即一个Task和线程催生以确保长期应用开始做不在JavaFX应用程序线程上发生。另请参阅在长时间应用程序初始化期间不同时间调用应用程序的方法,以使预加载程序知道初始化过程的当前状态,以便它可以实时准确地反映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(); 
          } 
         }); 
        } 
       } 
     });;     
    } 
}