Desidero caricare fino a nove pannelli in un TilePane. Per ogni pannello devo eseguire un calcolo del contenuto (circa 300 ms) e il secondo deve costruire il Pannello (circa 500 ms). Quello che voglio è che ci siano nove ProgressIndicators che si scambiano con ogni pannello dopo il suo calcolo. L'ho provato con il comando Platform.runlater e con una classe di servizio. Il risultato è sempre stato lo stesso. ProgressIndicator è mostrato, ma non animato. Dopo secondi ci sono tutti i pannelli contemporaneamente. Esiste la possibilità che gli Indicatori siano animati dal tempo di apertura e che io possa scambiarli uno dopo l'altro?Esegui attività in background in JavaFX
9
A
risposta
11
JavaFX ha Thread di invio eventi che utilizza per gli eventi dell'interfaccia utente. Tutto il lavoro con l'interfaccia utente dovrebbe avvenire su questo thread. E i calcoli non UI non dovrebbero accadere lì per evitare ritardi nell'interfaccia utente.
Vedi codice successivo:
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
Ecco come ho risolto il problema:
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
Grazie. Penso che il problema sia che un'attività (meglio una singola istanza di attività) non può essere eseguita più volte. Posizionare l'istanza dell'attività in un metodo che la reinizializza con ogni chiamata di metodo lo ha risolto anche per me. Bello :) –
Problemi correlati
- 1. Esegui attività in background in Javascript
- 2. esegui file bat in background
- 3. Esegui processo in background in Android
- 4. Debug delle attività in background
- 5. Heroku sedici attività in background
- 6. Esegui attività ant in jvm
- 7. JavaFX - Thread in background per query SQL
- 8. Esegui processi in background con beanstalk elastico
- 9. Esegui Jupyter Notebook in Background su Docker
- 10. Esegui alcune attività in IPython Notebook in modalità distaccata
- 11. Attività di rendering pesante (in tela) in blocchi JavaFX GUI
- 12. Affidabile attività in background ripetuta su Android
- 13. Android: Come avviare attività in background
- 14. Come posso coordinare due attività in background?
- 15. R Lucido - Attività in background continua
- 16. Simulazione di attività in background su AppHarbor
- 17. Avvio delle attività in background con Capistrano
- 18. Esegui attività in background ma restituisce risposta al client nell'applicazione Web ASP MVC
- 19. Esegui attività JavaExec in background e termina al completamento della build
- 20. attività di background java
- 21. Esegui attività in più thread su node.js
- 22. Esegui attività di build Android in attività personalizzate
- 23. Apri/Esegui fotocamera dal servizio in background in Android
- 24. Attività JavaFX: dove scrive updateMessage()?
- 25. Studio Android: attività in background in esecuzione indefinita
- 26. Esegui attività gradle su sottoprogetti
- 27. Esegui attività in base alle dipendenze in Go
- 28. Esegui applicazione Android dall'ultima attività
- 29. Android - Esegui in background - Servizio vs. classe Java Standard
- 30. Esegui il listener GPS in background su Android
Hi Sergey ... Ho una domanda, che può avere molti di questi thread in esecuzione nell'applicazione ? Grazie. –
@MarcoR, certo, puoi eseguire 'new Thread()' diverse volte. –
Grazie Sergey, è consigliabile avere più Platform.runLater nell'applicazione ??. Poiché questi thread devono cambiare la vista, per exampe se visualizzare una finestra di dialogo. –