implement cancel operation for image tagging
This commit is contained in:
parent
4ef219a8c1
commit
146db2c9c0
3 changed files with 84 additions and 30 deletions
|
@ -17,6 +17,7 @@ class MainPage : Application() {
|
|||
|
||||
fxmlLoader = FXMLLoader(MainPage::class.java.getResource("main-window-view.fxml"))
|
||||
val scene = Scene(fxmlLoader.load(), 640.0, 760.0)
|
||||
fxmlLoader.getController<MainPageController>().initialize()
|
||||
stage.title = "Image Tagger"
|
||||
stage.scene = scene
|
||||
stage.minWidth = 640.0
|
||||
|
|
|
@ -4,8 +4,11 @@ import dev.nuculabs.imagetagger.ai.ImageTagsPrediction
|
|||
import dev.nuculabs.imagetagger.ui.controls.ImageTagsEntryControl
|
||||
import javafx.application.Platform
|
||||
import javafx.fxml.FXML
|
||||
import javafx.scene.control.Button
|
||||
import javafx.scene.control.ProgressBar
|
||||
import javafx.scene.control.Separator
|
||||
import javafx.scene.layout.HBox
|
||||
import javafx.scene.layout.Priority
|
||||
import javafx.scene.layout.VBox
|
||||
import javafx.stage.FileChooser
|
||||
import java.io.File
|
||||
|
@ -50,6 +53,11 @@ class MainPageController {
|
|||
*/
|
||||
private val imageTagsPrediction = ImageTagsPrediction.getInstance()
|
||||
|
||||
/**
|
||||
* A boolean that when set to true it will stop the current image tagging operation.
|
||||
* When a new operation is started the boolean is reset to false.
|
||||
*/
|
||||
private var isCurrentTagsOperationCancelled: Boolean = false
|
||||
|
||||
@FXML
|
||||
private lateinit var progressBar: ProgressBar
|
||||
|
@ -57,6 +65,16 @@ class MainPageController {
|
|||
@FXML
|
||||
private lateinit var verticalBox: VBox
|
||||
|
||||
@FXML
|
||||
private lateinit var cancelButton: Button
|
||||
|
||||
/**
|
||||
* Initializes the controller. Needs to be called after the dependencies have been injected.
|
||||
*/
|
||||
fun initialize() {
|
||||
HBox.setHgrow(progressBar, Priority.ALWAYS)
|
||||
HBox.setHgrow(cancelButton, Priority.ALWAYS)
|
||||
}
|
||||
/**
|
||||
* Prompts the user to select files then predicts tags for the selected image files.
|
||||
*/
|
||||
|
@ -66,7 +84,9 @@ class MainPageController {
|
|||
val fileChooser = FileChooser().apply { title = "Choose images" }
|
||||
val filePaths = fileChooser.showOpenMultipleDialog(null) ?: return
|
||||
|
||||
isCurrentTagsOperationCancelled = false
|
||||
progressBar.isVisible = true
|
||||
cancelButton.isVisible = true
|
||||
progressBar.progress = 0.0
|
||||
imageFilesTotal = filePaths.count()
|
||||
processedImageFilesCount.set(0)
|
||||
|
@ -74,8 +94,18 @@ class MainPageController {
|
|||
Thread {
|
||||
logger.info("Analyzing $imageFilesTotal files")
|
||||
filePaths.forEach { filePath ->
|
||||
if (isCurrentTagsOperationCancelled) {
|
||||
logger.info("Cancelling current prediction operation.")
|
||||
return@Thread
|
||||
}
|
||||
workerSemaphore.acquire()
|
||||
workerPool.submit {
|
||||
if (isCurrentTagsOperationCancelled) {
|
||||
logger.info("Image prediction task is cancelled.")
|
||||
workerSemaphore.release()
|
||||
return@submit
|
||||
}
|
||||
|
||||
predictImageTags(
|
||||
filePath,
|
||||
onError = {
|
||||
|
@ -96,6 +126,16 @@ class MainPageController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the prediction operation.
|
||||
*/
|
||||
@FXML
|
||||
fun onCancelTagImagesClick() {
|
||||
isCurrentTagsOperationCancelled = true
|
||||
progressBar.isVisible = false
|
||||
cancelButton.isVisible = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicts an image tags and executes an action with it.
|
||||
*
|
||||
|
@ -140,6 +180,7 @@ class MainPageController {
|
|||
((processedImageFilesCount.incrementAndGet() * 100) / imageFilesTotal).toDouble() / 100.0
|
||||
if (processedImageFilesCount.get() == imageFilesTotal) {
|
||||
progressBar.isVisible = false
|
||||
cancelButton.isVisible = false
|
||||
logger.info("Finished processing images.")
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +189,7 @@ class MainPageController {
|
|||
* Shuts down the MainPageController.
|
||||
*/
|
||||
fun shutdown() {
|
||||
isCurrentTagsOperationCancelled = true
|
||||
workerPool.shutdownNow()
|
||||
}
|
||||
}
|
|
@ -5,35 +5,46 @@
|
|||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||
<BorderPane prefHeight="537.0" prefWidth="725.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17.0.2-ea" fx:controller="dev.nuculabs.imagetagger.ui.MainPageController">
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="30.0" right="30.0" top="20.0" />
|
||||
</padding>
|
||||
<top>
|
||||
<HBox alignment="CENTER_LEFT">
|
||||
<padding>
|
||||
<Insets bottom="5" left="5" right="5"/>
|
||||
</padding>
|
||||
<Button onAction="#onTagImagesButtonClick" text="Tag Images">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="far-images" iconSize="16"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Separator orientation="VERTICAL" style="-fx-padding: 10px" />
|
||||
</HBox>
|
||||
</top>
|
||||
<center>
|
||||
<ScrollPane>
|
||||
<VBox fx:id="verticalBox">
|
||||
</VBox>
|
||||
</ScrollPane>
|
||||
</center>
|
||||
<BorderPane prefHeight="537.0" prefWidth="725.0" xmlns:fx="http://javafx.com/fxml/1"
|
||||
xmlns="http://javafx.com/javafx/17.0.2-ea" fx:controller="dev.nuculabs.imagetagger.ui.MainPageController">
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="30.0" right="30.0" top="20.0"/>
|
||||
</padding>
|
||||
<top>
|
||||
<HBox alignment="CENTER_LEFT">
|
||||
<padding>
|
||||
<Insets bottom="5" left="5" right="5"/>
|
||||
</padding>
|
||||
<Button onAction="#onTagImagesButtonClick" text="Tag Images">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="far-images" iconSize="16"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Separator orientation="VERTICAL" style="-fx-padding: 10px"/>
|
||||
</HBox>
|
||||
</top>
|
||||
<center>
|
||||
<ScrollPane fitToWidth="true" fitToHeight="true">
|
||||
<VBox fx:id="verticalBox">
|
||||
</VBox>
|
||||
</ScrollPane>
|
||||
</center>
|
||||
|
||||
<bottom>
|
||||
<ProgressBar fx:id="progressBar" maxWidth="Infinity" visible="false">
|
||||
<padding>
|
||||
<Insets top="5" />
|
||||
</padding>
|
||||
</ProgressBar>
|
||||
</bottom>
|
||||
<bottom>
|
||||
<HBox alignment="CENTER_LEFT" prefWidth="Infinity">
|
||||
<padding>
|
||||
<Insets top="5"/>
|
||||
</padding>
|
||||
<ProgressBar fx:id="progressBar" maxWidth="Infinity" visible="false">
|
||||
<padding>
|
||||
<Insets right="5"/>
|
||||
</padding>
|
||||
</ProgressBar>
|
||||
<Button fx:id="cancelButton" onAction="#onCancelTagImagesClick" alignment="CENTER_RIGHT" visible="false">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="far-times-circle" iconColor="red" iconSize="16"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
</bottom>
|
||||
</BorderPane>
|
Loading…
Reference in a new issue