Sunday, October 18, 2015

Learn JavaFx 8, building user experience, Chapter 27

Listing 27-1. Performing a Long-Running Task in an Event Handler

import javafx.event
import javafx.event.EventHandler

import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.{Button, Label}
import scalafx.Includes._
import scalafx.scene.layout.{VBox, HBox}

object Blocking extends JFXApp {
  val statusLbl = new Label("Not started...")
  val startBtn = new Button("Start") {
    onAction = (e: ActionEvent) => runTask
  }
  val exitBtn = new Button("Exit") {
    onAction = (e: ActionEvent) => stage.close()
  }
  val buttonBox = new HBox(5, startBtn, exitBtn)
  val vBox = new VBox(10, statusLbl, buttonBox)

  def runTask = {
    for(i <- 1 to 10) {
      try {
        statusLbl.text = "Processing " + i + " of " + 10
        Thread.sleep(1000)
      } catch {
        case e: InterruptedException => e.printStackTrace()
      }
    }
  }

  stage = new PrimaryStage {
    title = "Blocking"
    scene = new Scene {
      root = vBox
    }
  }
}

Listing 27-2. A Program Accessing a Live Scene Graph from a Non-JavaFX Application Thread (and producing an error)

//BadUI
import javafx.event
import javafx.event.EventHandler

import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.{Button, Label}
import scalafx.Includes._
import scalafx.scene.layout.{VBox, HBox}

object Blocking extends JFXApp {
  val statusLbl = new Label("Not started...")
  val startBtn = new Button("Start") {
    onAction = (e: ActionEvent) => startTask
  }
  val exitBtn = new Button("Exit") {
    onAction = (e: ActionEvent) => stage.close()
  }
  val buttonBox = new HBox(5, startBtn, exitBtn)
  val vBox = new VBox(10, statusLbl, buttonBox)

  def startTask = {
    val backgroundThread = new Thread {
      setDaemon(true)
      override def run = {
        runTask
      }
    }
    backgroundThread.start()
  }

  def runTask = {
    for(i <- 1 to 10) {
      try {
        statusLbl.text = "Processing " + i + " of " + 10
        Thread.sleep(1000)
      } catch {
        case e: InterruptedException => e.printStackTrace()
      }
    }
  }

  stage = new PrimaryStage {
    title = "Blocking"
    scene = new Scene {
      root = vBox
    }
  }
}

Listing 27-3. A Responsive UI That Runs Long-Running Tasks in a Background Thread

import javafx.event
import javafx.event.EventHandler

import scalafx.application.{Platform, JFXApp}
import scalafx.application.JFXApp.PrimaryStage
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.{Button, Label}
import scalafx.Includes._
import scalafx.scene.layout.{VBox, HBox}

object Blocking extends JFXApp {
  val statusLbl = new Label("Not started...")
  val startBtn = new Button("Start") {
    onAction = (e: ActionEvent) => startTask
  }
  val exitBtn = new Button("Exit") {
    onAction = (e: ActionEvent) => stage.close()
  }
  val buttonBox = new HBox(5, startBtn, exitBtn)
  val vBox = new VBox(10, statusLbl, buttonBox)

  def startTask = {
    val backgroundThread = new Thread {
      setDaemon(true)
      override def run = {
        runTask
      }
    }
    backgroundThread.start()
  }

  def runTask = {
    for(i <- 1 to 10) {
      try {
        val status =  "Processing " + i + " of " + 10
        Platform.runLater {
          statusLbl.text = status
        }
        println(status)
        Thread.sleep(1000)
      } catch {
        case e: InterruptedException => e.printStackTrace()
      }
    }
  }

  stage = new PrimaryStage {
    title = "Blocking"
    scene = new Scene {
      root = vBox
    }
  }
}

0 comments: