How can I have a loading window appear whilst a process is running?

41 views Asked by At

I have a ScalaFX application that I would like to call a python script upon the clicking of an imageview. This python script will then write to a text file that the ScalaFX application will read from later. My current issue is that whilst the python script is running, I would like a loading screen to be shown but I'm having difficulties with this.

How the scene is invoked

new Menu("Floor Plan Gen") {
        items = List(new MenuItem("Select Image") {
          onAction = _ => {
            val fileChooser   = new FileChooser()
            fileChooser.initialDirectory =
              new File(System.getProperty("user.home"))
            fileChooser.title = "Select Image"
            val extensionList = List("*.png", "*.jpg", "*.jpeg", "*.gif")
            fileChooser.extensionFilters.add(new FileChooser.ExtensionFilter(
              "Image Files",
              extensionList.toSeq
            ))
            fileChooser.showOpenDialog(new Stage) match {
              case file: File =>
                println(
                  s"file location = ${file.toURI().toURL().toExternalForm()}"
                )
                val bufferedImage = ImageIO.read(file)
                val image: Image  = SwingFXUtils.toFXImage(bufferedImage, null)
                if (image.exception.value == null) {
                  val newWindow = new Stage()
                  val scene     = GraphGenWindow(
                    image,
                    model,
                    controller,
                    file.toPath().toString()
                  )
                  newWindow.resizable = false
                  newWindow.setTitle("Select Room")
                  newWindow.setScene(scene)
                  newWindow.show()
                } else {
                  controller.showError(
                    "Error",
                    "Error loading file.",
                    s"Failed to load file."
                  )
                }

              case _ =>
            }
          }
        })
      }

My first attempt

...Scene def....
onMouseClicked = event => {
    val x               = event.getX()
    val y               = event.getY()
    val roomFindCommand =
      Seq("python3", scriptLocation, fileName, x.toString(), y.toString())
    loadingWindow.show()
    roomFindCommand.!
    loadingWindow.close()
  }

When the screen is clicked, then the program freezes until the python script fully runs and then the loading window opens. I don't understand why this happens since the show() method should be invoked before the process begins. I understand that using ! will block the GUI thread but since I don't want the user to interact with the application and just wait whilst the script runs, then it should be ok. The close() method never seems to be invoked.

My second attempt

onMouseClicked = event => {
    val x               = event.getX()
    val y               = event.getY()
    val roomFindCommand =
      Seq("python3", scriptLocation, fileName, x.toString(), y.toString())
    
    val modelInvokerRunnable = new ModelInvokerRunnable(loadingWindow, roomFindCommand)
    val modelThread = new Thread(modelInvokerRunnable)
    modelThread.start()
    
    loadingWindow.show()
    
    Platform.runLater(new Runnable{
      override def run(): Unit = {
        println("HI THIS SHOULD RUN AT SOME POINT")
        loadingWindow.close()
      }
    })
  }
private class ModelInvokerRunnable(stage: Stage, script : Seq[String])    extends Runnable {

  override def run(): Unit                 = {
    script.!
  }
}

On this the loading window appeared straight after the click but again did not disappear afterwards. The print happened whilst the script was running but the window did not disappear.


On further investigation, when I reduced the onMouseClickEvent to just show and then close the stage, the stage stayed open which I find to be weird behaviour.

Any help would be much appreciated.

0

There are 0 answers