今天分享昨日未完的ProgressBar,今天總算有一個樣子了,經過在研讀關於FX中Concurrency相關的介面(Worker)與類別(Task),稍微有點心得,但還是覺得不是很熟悉,還有很屬性需要了解,包括Task的相關狀態屬性,以及Worker的屬性變化等,還需要多多練習,另外還有一個Service未提及,Task是只執行完成一次後便結束,Service則屬重複執行類別,使用方式下次再分享。
MyFXThread
package myfxthread;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
/**
*
* @author joombuopre
*/
public class MyFXThread extends Application {
private Elements el; //把所有的UI元件設定放在這個class裡
private Data data; //把FXThread相關的設定放在這裡
public MyFXThread(){
data=new Data(); //初始化Data
}
@Override
public void start(Stage primaryStage) {
el=new Elements(data); //因為ProgressBar的參數bind需要在data裡的ProgressProperty,才能動態顯示變化,
//所以需要傳入data物件
regEvent(); //把按鈕的案件註冊listener
primaryStage.setTitle("My Progress Bar");
primaryStage.setScene(el.scene);
primaryStage.show();
}
public void regEvent(){
el.sb.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t) {
Thread t1=new Thread((Runnable)data.worker);
t1.start(); //當使用者按下Start後便另開Thread,一直增加
}
});
el.cb.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t) {
data.worker.cancel();
}
});
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Elements
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderPaneBuilder;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
/**
*
* @author joombuopre
*/
public class Elements {
public Button sb=new Button("Start");
public Button cb=new Button("Cancel");
public Scene scene;
public ProgressBar pb=new ProgressBar();
public HBox hBox;
public BorderPane bl;
public Elements(Data data){
pb.setMinWidth(200);//設定progressbar的寬度
pb.progressProperty().bind(data.worker.progressProperty()); //這句最重要,要把progressbar的progress屬性bind到
//不斷增加的變數,這邊是thread裡面的work實例中的property屬性
hBox=HBoxBuilder.create() //使用xxxBuilder蠻好用的,可以一次就把要的屬性設定完成,最後在build
.padding(new Insets(10,10,10,10))
.spacing(10)
.alignment(Pos.CENTER)
.children(sb, cb)
.build();
scene= SceneBuilder.create()//使用xxxBuilder蠻好用的,可以一次就把要的屬性設定完成,最後在build
.root(BorderPaneBuilder.create()
.padding(new Insets(10,10,10,10))
.center(pb)
.bottom(hBox)
.build())
.build();
}
}
Data
package myfxthread;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
/**
*
* @author joombuopre
*/
public class Data {
public Worker<String> worker; //Thread在JavaFX有另外一個稱號Worker,Worker底下有很多參數代表該執行緒的狀況
public Data(){
worker = new Task<String>(){ //如果要執行某一項工作則是要new Task,然後override Call方法
@Override
protected String call() throws Exception {
final int total=100;
updateProgress(0, total); //updateProgress方法中,第一個參數是目前完成的數量,第二參數是預定要完成的全部數量
for (int i = 1; i <= total; i++) { //另外updateProgress會自動換算成百分比
try {
Thread.sleep(20); //利用sleep方法,讓UI看起來是慢慢增加
} catch (InterruptedException e) {
e.printStackTrace();
}
updateProgress(i, total);//隨i一直增加,progressbar就會趨近於full
}
return null;
}
};
}
}
成品: