Skip to content

Instantly share code, notes, and snippets.

@jewelsea
Last active April 5, 2023 11:53
Show Gist options
  • Save jewelsea/4989970 to your computer and use it in GitHub Desktop.
Save jewelsea/4989970 to your computer and use it in GitHub Desktop.
Demonstrates a JavaFX task which runs in the background reading data and, when required, pauses from reading data to prompt the user for extra input before continuing processing.
import java.util.concurrent.*;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.concurrent.Task;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
public class PromptingTaskDemo extends Application {
private static final String[] SAMPLE_TEXT =
"MISSING Lorem ipsum dolor sit amet MISSING consectetur adipisicing elit sed do eiusmod tempor incididunt MISSING ut labore et dolore magna aliqua"
.split(" ");
@Override public void start(Stage primaryStage) {
Label status = new Label();
ProgressBar progress = new ProgressBar();
VBox textContainer = new VBox(10);
textContainer.setStyle("-fx-background-color: burlywood; -fx-padding: 10;");
LoadTextTask task = new LoadTextTask(SAMPLE_TEXT, textContainer);
status.textProperty().bind(task.messageProperty());
progress.progressProperty().bind(task.progressProperty());
final Thread taskThread = new Thread(task, "label-generator");
taskThread.setDaemon(true);
VBox layout = new VBox(10);
layout.getChildren().addAll(status, progress, textContainer);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
primaryStage.setScene(new Scene(layout, 300, 700));
primaryStage.show();
taskThread.start();
}
public static void main(String[] args) { launch(args); }
}
class LoadTextTask extends Task<Void> {
private final String[] lines;
private final Pane container;
private final IntegerProperty idx = new SimpleIntegerProperty(0);
LoadTextTask(final String[] lines, final Pane container) {
this.lines = lines;
this.container = container;
}
@Override protected Void call() throws Exception {
try {
updateProgress(0, lines.length);
while (idx.get() < lines.length) {
final Label nextLabel = new Label();
final int curIdx = idx.get();
updateMessage("Reading Line: " + curIdx);
String nextText = lines[curIdx];
if ("MISSING".equals(nextText)) {
updateMessage("Prompting for missing text for line: " + curIdx);
FutureTask<String> futureTask = new FutureTask(
new MissingTextPrompt(
container.getScene().getWindow()
)
);
Platform.runLater(futureTask);
nextText = futureTask.get();
nextLabel.setStyle("-fx-background-color: palegreen;");
}
nextLabel.setText(nextText);
Platform.runLater(
new AddNodeLater(
container,
curIdx,
nextLabel
)
);
idx.set(curIdx + 1);
updateProgress(curIdx + 1, lines.length);
Thread.sleep(200);
}
updateMessage("Loading Text Completed: " + idx.get() + " lines loaded.");
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
class MissingTextPrompt implements Callable<String> {
final Window owner;
MissingTextPrompt(Window owner) {
this.owner = owner;
}
@Override public String call() throws Exception {
final Stage dialog = new Stage();
dialog.setTitle("Enter Missing Text");
dialog.initOwner(owner);
dialog.initStyle(StageStyle.UTILITY);
dialog.initModality(Modality.WINDOW_MODAL);
final TextField textField = new TextField();
final Button submitButton = new Button("Submit");
submitButton.setDefaultButton(true);
submitButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent t) {
dialog.close();
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER_RIGHT);
layout.setStyle("-fx-background-color: azure; -fx-padding: 10;");
layout.getChildren().setAll(textField, submitButton);
dialog.setScene(new Scene(layout));
dialog.showAndWait();
return textField.getText();
}
}
class AddNodeLater implements Runnable {
final Pane container;
final Node node;
final int idx;
public AddNodeLater(final Pane container, final int idx, final Node node) {
this.container = container;
this.node = node;
this.idx = idx;
}
@Override public void run() {
container.getChildren().add(idx, node);
}
}
}
@jewelsea
Copy link
Author

Answer to the StackOverflow question => JavaFX2: Can I pause a background Task / Service?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment