1. 程式人生 > >利用JavaFx開發RIA桌面應用-載入等待介面設計

利用JavaFx開發RIA桌面應用-載入等待介面設計

1 場景描述

JavaFX客戶端介面上的按鈕點選後會去查詢資料庫,固此操作很耗時,如果不做任務處理,將會出現假死現象,因此想給這個等待的過程載入一個等待動畫介面。

這個等待介面達到的效果就是,點選按鈕載入等待介面,任務執行結束,關閉等待介面,回到主介面。

2 實現效果

這裡寫圖片描述

3 具體過程

整個過程拆分為4塊:等待介面(new stage)、主頁面點選監聽、業務執行任務(task)、任務狀態監聽。

下面依據程式載入的順序來依次說明每一步。

第一步:主頁面點選監聽,這一步需要監聽主頁面引起這個事物的控制元件,比如我的是按鈕,下例子中是對ComboBox控制元件的滑鼠右鍵點選事件監聽。

// 主介面監聽
databaseNameInput.setOnMouseClicked(new ComboBoxMouseEvent());

// 實現監聽類
public class ComboBoxMouseEvent implements EventHandler<MouseEvent> {

    public void handle(MouseEvent mouseEvent) {

        MouseButton button = mouseEvent.getButton();

        if (button == MouseButton.SECONDARY) {

            MyTask task = new
MyTask(); task.valueProperty().addListener(new MyTaskListener()); ProgressFrom progressFrom = new ProgressFrom(task); progressFrom.activateProgressBar(); } } }

第二步:業務執行任務(task)的建立,即本事例中的資料庫查詢任務,這裡建立了一個MyTask類,call方法中即任務主體,任務執行完畢返回1。

public class
MyTask extends Task<Integer> {
private static final Logger logger = Logger.getLogger(MyTask.class); private String serverName; private String userName; private String passWord; private List<String> databaseList; private String exception; private int status; public int getStatus(){ return status; } public String getExceptions(){ return exception; } public List<String> getDatabaseList(){ return databaseList; } public MyTask(String serverName, String userName, String passWord){ this.serverName = serverName; this.userName = userName; this.passWord = passWord; } protected Integer call() throws Exception { DBHelper dbHelper = DBHelperObject.getInstance(); DBOperation dbOperation = DBOperationObject.getInstance(); dbHelper.setUrl(SQLUtil.getSQL(serverName,"master")); dbHelper.setUsername(userName); dbHelper.setPassword(passWord); Response response = dbHelper.getConnection(); if (response.getStatus() == 1){ logger.info("資料庫連線成功"); Response response1 = dbOperation.query(response.getConnection(), Constant.DEFALUT_SQL); if (response1.getStatus() == 1){ logger.info("資料查詢完成"); List<HashMap<String,Object>> list = response1.getList(); databaseList = MapUtil.getDatabaseList(list,"name"); status = 1; logger.info(databaseList); } else { exception = response1.getException(); } } else { exception = response.getException(); } if (exception != null && !exception.equals("")) { status = 0; logger.debug(exception); } return 1; }

第三步:任務狀態監聽,即主介面中需要對上步中建立的任務執行狀態做監聽,以便任務執行完畢更新主介面。

// 第一步中的方法代表了主介面的任務狀態監聽
task.valueProperty().addListener(new MyTaskListener());

// 具體監聽程式碼
public class MyTaskListener implements ChangeListener<Integer> {

    public void changed(ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) {

        if (task.getStatus() == 1) {

            // 獲取xml操作物件,讀取預設數值
            XMLFileServiceImpl xmlFileService = XMLFileObject.getInstance();

            List<String> databaseList = task.getDatabaseList();

            if (databaseList != null && databaseList.size() > 0) {
                ObservableList<String> database_items = FXCollections.observableList(databaseList);
                databaseName.setItems(database_items);
            }

        } else {

            String exception = task.getExceptions();

            if (exception != null && !exception.equals("")) {

                databaseName.setItems(null);
                Text text = new Text();
                text.setText(StringUtil.toConsoleString(exception));
                text.setFill(Color.RED);
                console.getChildren().add(text);
            }
        }
    }
}

第四步:啟動等待頁面,即new stage同時執行業務執行緒,此介面是一個透明的等待頁面,task執行結束後,頁面會自動關閉。

這裡需要注意一點:需要新增視窗父子關係屬性,不然載入視窗會與父視窗並存,形成2個視窗,解決這個問題只需要在載入頁面程式碼中新增dialogStage.ininOwner(primaryStage);這樣載入視窗就會與父視窗融合為一個視窗。

public class ProgressFrom {

    private static final Logger logger = Logger.getLogger(ProgressFrom.class);

    private Stage dialogStage;
    private ProgressIndicator progressIndicator;

    public ProgressFrom(final Task<?> task,Stage primaryStage) {

        dialogStage = new Stage();
        progressIndicator = new ProgressIndicator();

        // 視窗父子關係
        dialogStage.ininOwner(primaryStage);
        dialogStage.initStyle(StageStyle.UNDECORATED);
        dialogStage.initStyle(StageStyle.TRANSPARENT);
        dialogStage.initModality(Modality.APPLICATION_MODAL);

        // progress bar
        Label label = new Label("資料載入中, 請稍後...");
        label.setTextFill(Color.BLUE);
        //label.getStyleClass().add("progress-bar-root");
        progressIndicator.setProgress(-1F);
        //progressIndicator.getStyleClass().add("progress-bar-root");
        progressIndicator.progressProperty().bind(task.progressProperty());

        VBox vBox = new VBox();
        vBox.setSpacing(10);
        vBox.setBackground(Background.EMPTY);
        vBox.getChildren().addAll(progressIndicator,label);

        Scene scene = new Scene(vBox);
        scene.setFill(null);
        dialogStage.setScene(scene);

        Thread inner = new Thread(task);
        inner.start();

        task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            public void handle(WorkerStateEvent event) {
                dialogStage.close();
            }
        });

        logger.info("UI");
    }

    public void activateProgressBar() {
        dialogStage.show();
    }

    public Stage getDialogStage(){
        return dialogStage;
    }

    public void cancelProgressBar() {
        dialogStage.close();
    }
}

相關文章: