你好,欢迎访问我的博客!登录
当前位置:首页 - JavaFX - 正文 求知成瘾,却无作品!

JavaFX为应用程序使用预加载器

2016-06-02JavaFX攻城狮2460°c
A+ A-

一般情况下,在应用程序启动的时候都会执行一些初始化操作,比如版本检查、插件加载、数据库初始化等等,这个时候用预加载器显示一些进度信息会让用户体验相对好很多,如果不显示加载进度,主程序一时难以初始化完,在显示主程序之前的这段空档时间就会造成很不好的用户体验。

刚刚从oracle官网学习了预加载器有关的东西,因为自己要用,所以在这里简单加以记录,具体用的时候根据个人需求不同拓展这个简单的例子即可。

目前我还不会直接将预加载器挂载到主程序上面,所以如果是主程序已经开发一半了,发现需要预加载器,那么就需要学习如何为程序添加预加载器,可以到官方教程里面研究一下:

官方网站预加载器教程

我的开发工具是NetBeans 8.1,借助工具可以很容易实现:

  • 在菜单栏中选择文件,然后选择新建项目

  • 在弹出的选框中选择类别为JavaFX,项目选择为JavaFX FXML 应用程序

  • 点击下一步按钮,填写项目名称等信息,勾选创建定制预加载器,点击完成按钮

1.gif

将预加载器和主程序发生关联关系

创建完项目后,会同时生成两个项目,一个是应用程序本身,还有一个就是预加载器程序

QQ截图20160602184254.png

可以看出主程序的库中引用了预加载器

这时候对预加载器项目内的包上点击右键执行编译包命令

QQ截图20160602184627.png

然后在主程序项目上点击鼠标右键,选择清理并构建,然后继续在主程序项目上点击鼠标右键,运行项目,仔细看会发现预加载器一闪而过,然后主界面出现,但是这里我们需要通过自己的逻辑业务来控制预加载器的显示与隐藏。

在主程序中添加控制预加载器的方法:

package javafxapplication6;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.application.Preloader;
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;
import javafx.stage.StageStyle;

/**
 *
 * @author Administrator
 */
public class JavaFXApplication6 extends Application {
    BooleanProperty ready=new SimpleBooleanProperty(false);
    private void longStart(){
        Task task=new Task<Void>(){
          protected  Void call()throws Exception{
           int max=10;
           for(int i=1;i<=max;i++){
               Thread.sleep(200);
               notifyPreloader(new Preloader.ProgressNotification(((double) i)/max));//更新进度条
           }
           //改变准备状态为true
           ready.setValue(Boolean.TRUE);
           //告诉进度条主程序初始化完毕
           notifyPreloader(new Preloader.StateChangeNotification(Preloader.StateChangeNotification.Type.BEFORE_START));
           return null;
          }
        };
        new Thread(task).start();
    }
    @Override
    public void start(Stage stage) throws Exception {
        longStart();
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        //stage.initStyle(StageStyle.UNDECORATED);//设定窗口无边框
       //监听准备状态
        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();//显示主窗体
                        }
                    });
                }
            }
        });
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
    
}

改变预加载器的实现方式:

package javafxapplication6.preloader;

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;
import javafx.stage.StageStyle;

/**
 * Simple Preloader Using the ProgressBar Control
 *
 * @author Administrator
 */
public class JavaFXApplication6_Preloader extends Preloader {
    
    ProgressBar bar;
    Stage stage;
    boolean noLoadingProgress=true;
    
    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.initStyle(StageStyle.UNDECORATED);//取消窗体边框
        stage.show();
    }
    
    @Override
    public void handleStateChangeNotification(StateChangeNotification scn) {

    }
    
    @Override
    public void handleProgressNotification(ProgressNotification pn) {
        if(pn.getProgress()!=1.0||noLoadingProgress){
            bar.setProgress(pn.getProgress()/2);
            if(pn.getProgress()>0){
                noLoadingProgress=false;
            }
        }
        bar.setProgress(pn.getProgress());
    }  

    @Override
    public void handleApplicationNotification(PreloaderNotification info) {
       if(info instanceof ProgressNotification){//更新进度条
           double v=((ProgressNotification) info).getProgress();
           if(!noLoadingProgress){
               v=0.5+v/2;
           }
           bar.setProgress(v);
       }else if(info instanceof StateChangeNotification){//主程序加载完毕
           stage.hide();//进度条隐藏
       }
    }
    
    
}

根据上面的方式改变后,运行起来就发现当进度条走完后主界面才会显示出来:

2.gif


这样子,通过自定义主程序中的预加载逻辑就可以和预加载器完美配合了。


标签:

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。


  登录