In a distinct thread
, a fresh task
initiates a file dialogue
via a FileChooser
object to save the data in Excel or JSON format.
The getFileSavingDialogue method starts the file chooser's save dialogue utilizing Platform.runLater
to handle it on the UI thread
as it's a UI operation
This function only returns the file the user chooses after clicking the save button
of the dialogue. To facilitate this, an AtomicReference fileRef
is used. The loop persists until a file is selected and referenced by fileRef.
private File getFileSavingDialogue() {
AtomicReference<File> fileRef = new AtomicReference<>();
Platform.runLater(() -> {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save publications");
FileChooser.ExtensionFilter extFilter;
if (Objects.equals(savingOption, "excel")) {
extFilter = new FileChooser.ExtensionFilter("Excel (*.csv)", "*.csv");
fileChooser.setInitialFileName("result.csv");
} else {
extFilter = new FileChooser.ExtensionFilter("JSON file", "*.json");
fileChooser.setInitialFileName("result.json");
}
fileChooser.getExtensionFilters().add(extFilter);
fileRef.set(fileChooser.showSaveDialog(parentWindow));
});
while (fileRef.get() == null) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
return fileRef.get();
}
This is the call method of the Task:
@Override
protected Void call() {
FINAL_PATH = getFileSavingDialogue().getAbsolutePath();
try {
Thread.sleep(3000);
if (savingOption.equals("excel"))
if (saveToExcel())
System.out.println("Writing Excel file was successful");
else if (savingOption.equals("json"))
if (saveToJSON())
System.out.println("Writing JSON file was successful");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
return null;
}
This is the event handler of the button that initiated the saving process:
saveButton.setOnAction(event -> {
saveButton.setDisable(true);
backButton.setDisable(true);
SavePublications saveDataTask = new SavePublications(rootNode.getScene().getWindow(), result);
if (currentOption.equals("excel"))
saveDataTask.setSavingOption("excel");
else
saveDataTask.setSavingOption("json");
saveDataTask.setOnSucceeded(e -> {
saveButton.setDisable(false);
backButton.setDisable(false);
});
saveDataTask.setOnCancelled(e -> {
saveButton.setDisable(false);
backButton.setDisable(false);
});
new Thread(saveDataTask).start();
});
My issue is that if the user closes that dialogue window, both saveButton
and backButton
in the view will be disabled and never be enabled again because the task started and will never finish or be canceled.
How can I detect that the dialogue window was closed and reenable the buttons again?
I think you are going to need to structure things differently. See if this example and help.
It uses FileChooser to get the File to save to. From there, one of two tasks is run depending on the file type.
package org.example;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
public class App extends Application {
File saveFile;
Task<Void> saveToFileTask;
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
primaryStage.setTitle("JavaFX WebView Example");
Button btnSave = new Button("Save");
Button btnCancel = new Button("Cancel");
btnCancel.setDisable(true);
ProgressBar progressBar = new ProgressBar();
progressBar.setVisible(false);
btnSave.setOnAction(actionEvent -> {
saveFile = saveToFile(primaryStage);
if(saveFile != null)
{
btnSave.setDisable(true);
btnCancel.setDisable(false);
progressBar.setVisible(true);
if(saveFile.getName().endsWith(".csv"))
{
saveToFileTask = writeCsvFile(saveFile);
}
else
{
saveToFileTask = writeTsvFile(saveFile);
}
saveToFileTask.setOnSucceeded(onSucceeded -> {
btnSave.setDisable(false);
btnCancel.setDisable(true);
progressBar.setVisible(false);
});
saveToFileTask.setOnCancelled(onCancelled -> {
btnSave.setDisable(false);
btnCancel.setDisable(true);
progressBar.setVisible(false);
});
progressBar.progressProperty().bind(saveToFileTask.progressProperty());
Thread thread = new Thread(saveToFileTask);
thread.setDaemon(true);
thread.start();
}
});
btnCancel.setOnAction(onAction -> {
saveToFileTask.cancel();
});
VBox root = new VBox(btnSave, btnCancel, progressBar);
Scene scene = new Scene(root, 960, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public File saveToFile(Stage stage)
{
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save");
fileChooser.getExtensionFilters().addAll(new ExtensionFilter("CSV file", "*.csv"), new ExtensionFilter("TSV file", "*.tsv"));
return fileChooser.showSaveDialog(stage);
}
public Task<Void> writeCsvFile(File file)
{
Task<Void> writeToCsvFile = new Task<Void>() {
@Override
protected Void call(){
StringBuilder stringBuilder = new StringBuilder();
//Do do this! Use a library!
for(int i = 1; i <= 100; i++)
{
stringBuilder.append(i).append(",");
if(i % 10 == 0)
{
stringBuilder.append(System.lineSeparator());
}
//help simulate a long task!
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
updateProgress(i, 100);
}
try
{
System.out.println(stringBuilder.toString());
Files.write(file.toPath(), stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return null;
}
};
return writeToCsvFile;
}
public Task<Void> writeTsvFile(File file)
{
Task<Void> writeToTsvFile = new Task<Void>() {
@Override
protected Void call(){
StringBuilder stringBuilder = new StringBuilder();
//Do do this! Use a library!
for(int i = 1; i <= 100; i++)
{
stringBuilder.append(i).append("\t");
if(i % 10 == 0)
{
stringBuilder.append(System.lineSeparator());
}
//help simulate a long task!
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
updateProgress(i, 100);
}
try
{
System.out.println(stringBuilder.toString());
Files.write(file.toPath(), stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return null;
}
};
return writeToTsvFile;
}
}