Skip to content

Commit b6c6b47

Browse files
committed
Task are now run async. JavaFX Thread doesn't lock while the app is performing tasks.
1 parent cab54ab commit b6c6b47

File tree

2 files changed

+65
-42
lines changed

2 files changed

+65
-42
lines changed

src/main/java/app/controller/MainController.java

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
import app.model.Operations;
55
import app.model.ProtectionCustomSetting;
66
import app.service.TaskManager;
7+
import javafx.application.Platform;
78
import javafx.collections.FXCollections;
89
import javafx.fxml.FXML;
910
import javafx.fxml.Initializable;
11+
import javafx.scene.Cursor;
1012
import javafx.scene.control.Alert;
13+
import javafx.scene.control.Button;
1114
import javafx.scene.control.CheckBox;
1215
import javafx.scene.control.ChoiceBox;
1316
import javafx.scene.control.TextField;
@@ -21,6 +24,7 @@
2124
import java.net.URL;
2225
import java.util.LinkedHashMap;
2326
import java.util.ResourceBundle;
27+
import java.util.concurrent.CompletableFuture;
2428

2529
public class MainController implements Initializable {
2630
private LinkedHashMap<String, Integer> protectionLevelsOptions;
@@ -33,7 +37,6 @@ public class MainController implements Initializable {
3337
@FXML
3438
private TextField outputPathTextField;
3539

36-
3740
@FXML
3841
private ChoiceBox<String> protectionLevelsChoiceBox;
3942

@@ -46,6 +49,9 @@ public class MainController implements Initializable {
4649
@FXML
4750
private VBox protectionAdvancedSettingsContainer;
4851

52+
@FXML
53+
private Button runButton;
54+
4955
@Override
5056
public void initialize(URL location, ResourceBundle resources) {
5157
setOperations();
@@ -55,19 +61,8 @@ public void initialize(URL location, ResourceBundle resources) {
5561

5662
@FXML
5763
private void runApplication() {
58-
ApplicationExecutionSettings settings = new ApplicationExecutionSettings(
59-
sourcePathTextField.getText(),
60-
outputPathTextField.getText(),
61-
getOperations(),
62-
getProtectionLevel(),
63-
getProtectionCustomSetting()
64-
);
65-
try {
66-
long elapsedTime = TaskManager.runApplicationWithSettings(settings);
67-
displaySucces(elapsedTime);
68-
} catch (Error error) {
69-
displayError(error);
70-
}
64+
ApplicationExecutionSettings settings = getApplicationExecutionSettings();
65+
runApplicationAsync(settings);
7166
}
7267

7368
@FXML
@@ -113,6 +108,38 @@ private void displayAbout() {
113108
alert.showAndWait();
114109
}
115110

111+
private void runApplicationAsync(ApplicationExecutionSettings settings) {
112+
// Change the UI to reflect that the app is running
113+
this.runButton.setDisable(true);
114+
this.runButton.getScene().setCursor(Cursor.WAIT);
115+
// Run tasks asynchronously
116+
CompletableFuture
117+
.supplyAsync(() -> TaskManager.runApplicationWithSettings(settings))
118+
.handle((elapsedTime, error) -> {
119+
if (error == null) {
120+
Platform.runLater(() -> displaySucces(elapsedTime));
121+
} else {
122+
Platform.runLater(() -> displayError(error.getCause().getMessage()));
123+
}
124+
// Restore the UI
125+
Platform.runLater(() -> {
126+
this.runButton.setDisable(false);
127+
this.runButton.getScene().setCursor(Cursor.DEFAULT);
128+
});
129+
return null;
130+
});
131+
}
132+
133+
private ApplicationExecutionSettings getApplicationExecutionSettings() {
134+
return new ApplicationExecutionSettings(
135+
sourcePathTextField.getText(),
136+
outputPathTextField.getText(),
137+
getOperations(),
138+
getProtectionLevel(),
139+
getProtectionCustomSetting()
140+
);
141+
}
142+
116143
private void setOperations() {
117144
operationsChoiceBox.setItems(
118145
FXCollections.observableArrayList(
@@ -198,11 +225,11 @@ private void displaySucces(long elapsedTime) {
198225
alert.showAndWait();
199226
}
200227

201-
private void displayError(Error error) {
228+
private void displayError(String message) {
202229
Alert alert = new Alert(Alert.AlertType.ERROR);
203230
alert.setTitle("Error");
204231
alert.setHeaderText("Ooops, something went wrong!");
205-
alert.setContentText(error.getMessage());
232+
alert.setContentText(message);
206233
alert.showAndWait();
207234
}
208235
}

src/main/resources/app/fxml/main.fxml

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,73 +14,69 @@
1414
<?import javafx.scene.layout.HBox?>
1515
<?import javafx.scene.layout.VBox?>
1616

17-
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="600.0" spacing="20.0"
18-
xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
19-
fx:controller="app.controller.MainController">
17+
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="600.0" spacing="20.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.controller.MainController">
2018
<padding>
21-
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
19+
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
2220
</padding>
2321
<AnchorPane VBox.vgrow="NEVER">
2422
<padding>
25-
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
23+
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
2624
</padding>
2725
<VBox.margin>
28-
<Insets/>
26+
<Insets />
2927
</VBox.margin>
3028
<Button contentDisplay="RIGHT" layoutX="475.0" layoutY="22.0" mnemonicParsing="false"
3129
onAction="#displayAbout" prefWidth="115.0" text="About" AnchorPane.rightAnchor="0.0"/>
3230
<ImageView fitHeight="150.0" fitWidth="200.0" onMouseClicked="#openSite" pickOnBounds="true"
3331
preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
3432
AnchorPane.topAnchor="0.0">
3533
<cursor>
36-
<Cursor fx:constant="HAND"/>
34+
<Cursor fx:constant="HAND" />
3735
</cursor>
38-
<Image url="@../img/unsl_logo.png"/>
36+
<Image url="@../img/unsl_logo.png" />
3937
</ImageView>
4038
</AnchorPane>
41-
<Separator prefWidth="200.0"/>
39+
<Separator prefWidth="200.0" />
4240
<HBox spacing="20.0" VBox.vgrow="NEVER">
43-
<Label minWidth="-Infinity" prefWidth="80.0" text="Source File:"/>
44-
<TextField fx:id="sourcePathTextField" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS"/>
41+
<Label minWidth="-Infinity" prefWidth="80.0" text="Source File:" />
42+
<TextField fx:id="sourcePathTextField" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS" />
4543
<Button mnemonicParsing="false" onAction="#setSourcePath">
4644
<graphic>
4745
<ImageView fitHeight="30.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
48-
<Image url="@../icon/folder.png"/>
46+
<Image url="@../icon/folder.png" />
4947
</ImageView>
5048
</graphic>
5149
</Button>
5250
</HBox>
5351
<HBox layoutX="20.0" layoutY="132.0" spacing="20.0">
54-
<Label minWidth="-Infinity" prefWidth="80.0" text="Output File:"/>
55-
<TextField fx:id="outputPathTextField" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS"/>
52+
<Label minWidth="-Infinity" prefWidth="80.0" text="Output File:" />
53+
<TextField fx:id="outputPathTextField" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS" />
5654
<Button mnemonicParsing="false" onAction="#setOutputPath">
5755
<graphic>
5856
<ImageView fitHeight="30.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
59-
<Image url="@../icon/folder.png"/>
57+
<Image url="@../icon/folder.png" />
6058
</ImageView>
6159
</graphic>
6260
</Button>
6361
</HBox>
64-
<Separator prefWidth="200.0"/>
62+
<Separator prefWidth="200.0" />
6563
<HBox alignment="CENTER_LEFT" spacing="50.0" VBox.vgrow="NEVER">
66-
<Label text="Operation(s):"/>
67-
<ChoiceBox fx:id="operationsChoiceBox" prefWidth="150.0"/>
64+
<Label text="Operation(s):" />
65+
<ChoiceBox fx:id="operationsChoiceBox" prefWidth="150.0" />
6866
</HBox>
69-
<Separator layoutX="20.0" layoutY="222.0" prefWidth="200.0"/>
67+
<Separator layoutX="20.0" layoutY="222.0" prefWidth="200.0" />
7068
<VBox fx:id="protectionAdvancedSettingsContainer" spacing="20.0">
71-
<Label text="Protection Advanced Settings:"/>
69+
<Label text="Protection Advanced Settings:" />
7270
<HBox alignment="CENTER_LEFT" spacing="50.0">
73-
<ChoiceBox fx:id="protectionLevelsChoiceBox" prefWidth="150.0"/>
74-
<CheckBox fx:id="protectionCustomSetting" mnemonicParsing="false" text="CustomSetting"/>
71+
<ChoiceBox fx:id="protectionLevelsChoiceBox" prefWidth="150.0" />
72+
<CheckBox fx:id="protectionCustomSetting" mnemonicParsing="false" text="CustomSetting" />
7573
</HBox>
7674
</VBox>
7775
<AnchorPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
78-
<Button contentDisplay="RIGHT" defaultButton="true" graphicTextGap="10.0" mnemonicParsing="false"
79-
onAction="#runApplication" prefWidth="115.0" text="Run" AnchorPane.bottomAnchor="0.0"
80-
AnchorPane.rightAnchor="0.0">
76+
<Button fx:id="runButton" contentDisplay="RIGHT" defaultButton="true" graphicTextGap="10.0" mnemonicParsing="false" onAction="#runApplication" prefWidth="115.0" text="Run" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0">
8177
<graphic>
8278
<ImageView fitHeight="150.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
83-
<Image url="@../icon/startup.png"/>
79+
<Image url="@../icon/startup.png" />
8480
</ImageView>
8581
</graphic>
8682
</Button>

0 commit comments

Comments
 (0)