利用JavaFx開發RIA桌面應用-載入等待介面設計
阿新 • • 發佈:2019-02-01
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();
}
}
相關文章: