我想在TilePane中加載最多九個面板。對於每個窗格,我必須首先運行內容計算(大約300ms),其次是構建面板(大約500ms)。我想要的是,有9個ProgressIndicators在計算後與每個面板進行交換。 我使用Platform.runlater命令以及服務類來試用它。結果總是一樣的。 ProgressIndicator顯示,但不是動畫。幾秒鐘後,所有的面板一次。 有沒有可能,指標是動畫空洞時間,我可以一個接一個地交換它們?JavaFX在後臺執行任務
9
A
回答
11
JavaFX有用於UI事件的Event Dispatch Thread。所有使用UI的工作都應該發生在這個線程上。非UI計算不應該發生在那裏以避免UI中的滯後。
見下面的代碼:
public class Indicators extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Pane root = new HBox();
stage.setScene(new Scene(root, 300, 100));
for (int i = 0; i < 10; i++) {
final ProgressIndicator pi = new ProgressIndicator(0);
root.getChildren().add(pi);
// separate non-FX thread
new Thread() {
// runnable for that thread
public void run() {
for (int i = 0; i < 20; i++) {
try {
// imitating work
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
final double progress = i*0.05;
// update ProgressIndicator on FX thread
Platform.runLater(new Runnable() {
public void run() {
pi.setProgress(progress);
}
});
}
}
}.start();
}
stage.show();
}
}
12
這是我如何解決了這個問題:
import java.util.Random;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Minimal extends Application {
private TilePane loadPane;
private ProgressIndicator[] indicators = new ProgressIndicator[9];
private Label loading[] = new Label[9];
private Color[] colors = {Color.BLACK,Color.BLUE,Color.CRIMSON,Color.DARKCYAN,Color.FORESTGREEN,Color.GOLD,Color.HOTPINK,Color.INDIGO,Color.KHAKI};
private int counter = 0;
@Override
public void start(Stage primaryStage) throws Exception {
//creating Layout
final Group root = new Group();
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
StackPane waitingPane = new StackPane();
final ProgressBar progress = new ProgressBar();
Label load = new Label("loading things...");
progress.setTranslateY(-25);
load.setTranslateY(25);
waitingPane.getChildren().addAll(new Rectangle(400,400,Color.WHITE),load,progress);
root.getChildren().add(waitingPane);
//Task for computing the Panels:
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
final double prog = i*0.05;
Platform.runLater(new Runnable() {
public void run() {
progress.setProgress(prog);
}
});
}
return null;
}
};
//stateProperty for Task:
task.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends State> observable,
State oldValue, Worker.State newState) {
if(newState==Worker.State.SUCCEEDED){
loadPanels(root);
}
}
});
//start Task
new Thread(task).start();
primaryStage.show();
}
private void loadPanels(Group root) {
//change to loadPanel:
root.getChildren().set(0,createLoadPane());
//Service:
final Service<Rectangle> RecBuilder = new Service<Rectangle>() {
@Override protected Task<Rectangle> createTask() {
return new Task<Rectangle>() {
@Override protected Rectangle call() throws InterruptedException {
updateMessage("loading rectangle . . .");
updateProgress(0, 10);
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
}
updateMessage("Finish!");
return new Rectangle((380)/3,(380)/3,colors[counter]);
}
};
}
};
//StateListener
RecBuilder.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override public void changed(ObservableValue<? extends Worker.State> observableValue,
Worker.State oldState, Worker.State newState) {
switch (newState) {
case SCHEDULED:
break;
case READY:
case RUNNING:
break;
case SUCCEEDED:
Rectangle rec = RecBuilder.valueProperty().getValue();
indicators[counter].progressProperty().unbind();
loading[counter].textProperty().unbind();
loadPane.getChildren().set(counter, rec);
if(counter<8){
counter++;
nextPane(RecBuilder);
}
break;
case CANCELLED:
case FAILED:
loading[counter].textProperty().unbind();
loading[counter].setText("Failed!");
if(counter<8){
counter++;
nextPane(RecBuilder);
}
break;
}
}
});
//begin PanelBuilding:
nextPane(RecBuilder);
}
private void nextPane(Service<Rectangle> recBuilder) {
loading[counter].textProperty().bind(recBuilder.messageProperty());
indicators[counter].visibleProperty().bind(recBuilder.progressProperty().isNotEqualTo(new SimpleDoubleProperty(ProgressBar.INDETERMINATE_PROGRESS)));
recBuilder.restart();
}
private Node createLoadPane() {
loadPane = new TilePane(5,5);
loadPane.setPrefColumns(3);
loadPane.setPadding(new Insets(5));
for(int i=0;i<9;i++){
StackPane waitingPane = new StackPane();
Rectangle background = new Rectangle((380)/3, (380)/3, Color.WHITE);
indicators[i] = new ProgressIndicator();
indicators[i].setPrefSize(50, 50);
indicators[i].setMaxSize(50, 50);
indicators[i].setTranslateY(-25);
indicators[i].setTranslateX(-10);
loading[i] = new Label();
loading[i].setTranslateY(25);
waitingPane.getChildren().addAll(background,indicators[i],loading[i]);
loadPane.getChildren().add(waitingPane);
}
return loadPane;
}
public static void main(String[] args) {
launch(args);
}
}
+0
謝謝。我認爲問題是一個任務(更好的單個任務實例)不能運行多次。將任務實例放在一個方法中,讓我們通過每個方法調用重新初始化它,這也爲我解決了這個問題。尼斯:) – 2015-04-18 13:01:33
相關問題
- 1. 在後臺執行任務
- 2. JavaFX中運行的後臺任務
- 3. 任務完成後JavaFX執行代碼
- 4. 在後臺繼續執行任務
- 5. 使用NSThread在後臺執行任務
- 6. 在asp.net中執行後臺任務MVC4
- 7. 如何在後臺執行Android任務
- 8. 如何在後臺執行任務?
- 9. UWP後臺任務未執行
- 10. 防止執行dispatch_after()後臺任務
- 11. JavaFX網絡後臺任務與javafx.concurrent
- 12. JavaFX GUI發佈後臺任務
- 13. javafx後臺任務:在另一個服務中調用服務
- 14. 延遲後在iOS上執行後臺任務
- 15. Android服務定期在後臺執行任務嗎?
- 16. 在rails中立即並行執行的後臺任務
- 17. 在後臺運行一個任務並繼續執行
- 18. Android重複執行任務在後臺運行
- 19. JavaFX的後臺任務沒有運行不止一次
- 20. 後臺任務只運行
- 21. 後臺任務
- 22. IIS可以託管WCF服務執行後臺任務嗎?
- 23. 在iOS中的不同線程上執行後臺任務
- 24. 在後臺執行遊戲中的得分任務objective-c
- 25. 如何在Android中定期執行後臺任務?
- 26. 什麼方法可用於在後臺執行任務
- 27. 在後臺執行網絡和其他耗時任務
- 28. 在iPhone上的應用程序中執行後臺任務
- 29. 在Rails控制器執行很短的後臺任務
- 30. 如何在後臺執行完成的下載任務?
喜謝爾蓋......我有一個問題,我可以有幾個在應用程序中運行這些線程?謝謝。 – 2015-06-22 15:24:36
@MarcoR,當然,你可以多次運行'new Thread()'。 – 2015-06-22 16:27:18
謝謝謝爾蓋,建議在應用程序中有幾個Platform.runLater ??。由於這些線程必須更改視圖,以檢查是否顯示對話框。 – 2015-06-22 16:47:59