score:7
For scala 2.10
You can use scala.concurrent.future
and then register a callback on completion. The callback will update the GUI on the EDT thread.
Lets do it!
//in your swing gui event listener (e.g. button clicked, combo selected, ...)
import scala.concurrent.future
//needed to execute futures on a default implicit context
import scala.concurrent.ExecutionContext.Implicits._
val backgroundOperation: Future[Result] = future {
//... do that thing, on another thread
theResult
}
//this goes on without blocking
backgroundOperation onSuccess {
case result => Swing.onEDT {
//do your GUI update here
}
}
This is the most simple case:
- we're updating only when done, with no progress
- we're only handling the successful case
To deal with (1) you could combine different futures, using the map
/flatMap
methods on the Future
instance. As those gets called, you can update the progress in the UI (always making sure you do it in a Swing.onEDT
block
//example progress update
val backgroundCombination = backgroundOperation map { partial: Result =>
progress(2)
//process the partial result and obtain
myResult2
} //here you can map again and again
def progress(step: Int) {
Swing.onEDT {
//do your GUI progress update here
}
}
To deal with (2) you can register a callback onFailure
or handle both cases with the onComplete
.
For relevant examples: scaladocs and the relevant SIP (though the SIP examples seems outdated, they should give you a good idea)
score:0
If you need something simple you can run the long task in a new Thread and just make sure to update it in the EDT:
def swing(task: => Unit) = SwingUtilities.invokeLater(new Runnable {
def run() { task }
})
def thread(task: => Unit) = new Thread(new Runnable {
def run() {task}
}).run()
thread({
val stuff = longRunningTask()
swing(updateGui(stuff))
})
score:0
You can define your own ExecutionContext
which will execute anything on the Swing Event Dispatch Thread using SwingUtilities.invokeLater
and then use this context to schedule a code which needs to be executed by Swing, still retaining the ability to chain Future
s the Scala way, including passing results between them.
import javax.swing.SwingUtilities
import scala.concurrent.ExecutionContext
object OnSwing extends ExecutionContext {
def execute(runnable: Runnable) = {
SwingUtilities.invokeLater(runnable)
}
def reportFailure(cause: Throwable) = {
cause.printStackTrace()
}
}
case ButtonClicked(_) =>
Future {
doLongBackgroundProcess("Timestamp")
}.foreach { result =>
txtStatus.text = result
}(OnSwing)
score:5
If you want to use Actors, following may work for you.
There are two actors:
- WorkerActor which does data processing (here, there is simple loop with Thread.sleep). This actor sends messages about progress of work to another actor:
- GUIUpdateActor - receives updates about progress and updates UI by calling handleGuiProgressEvent method
UI update method handleGuiProgressEvent receives update event. Important point is that this method is called by Actor using one of Akka threads and uses Swing.onEDT to do Swing work in Swing event dispatching thread.
You may add following to various places to see what is current thread.
println("Current thread:" + Thread.currentThread())
Code is runnable Swing/Akka application.
import akka.actor.{Props, ActorRef, Actor, ActorSystem}
import swing._
import event.ButtonClicked
trait GUIProgressEventHandler {
def handleGuiProgressEvent(event: GuiEvent)
}
abstract class GuiEvent
case class GuiProgressEvent(val percentage: Int) extends GuiEvent
object ProcessingFinished extends GuiEvent
object SwingAkkaGUI extends SimpleSwingApplication with GUIProgressEventHandler {
lazy val processItButton = new Button {text = "Process it"}
lazy val progressBar = new ProgressBar() {min = 0; max = 100}
def top = new MainFrame {
title = "Swing GUI with Akka actors"
contents = new BoxPanel(Orientation.Horizontal) {
contents += processItButton
contents += progressBar
contents += new CheckBox(text = "another GUI element")
}
val workerActor = createActorSystemWithWorkerActor()
listenTo(processItButton)
reactions += {
case ButtonClicked(b) => {
processItButton.enabled = false
processItButton.text = "Processing"
workerActor ! "Start"
}
}
}
def handleGuiProgressEvent(event: GuiEvent) {
event match {
case progress: GuiProgressEvent => Swing.onEDT{
progressBar.value = progress.percentage
}
case ProcessingFinished => Swing.onEDT{
processItButton.text = "Process it"
processItButton.enabled = true
}
}
}
def createActorSystemWithWorkerActor():ActorRef = {
def system = ActorSystem("ActorSystem")
val guiUpdateActor = system.actorOf(
Props[GUIUpdateActor].withCreator(new GUIUpdateActor(this)), name = "guiUpdateActor")
val workerActor = system.actorOf(
Props[WorkerActor].withCreator(new WorkerActor(guiUpdateActor)), name = "workerActor")
workerActor
}
class GUIUpdateActor(val gui:GUIProgressEventHandler) extends Actor {
def receive = {
case event: GuiEvent => gui.handleGuiProgressEvent(event)
}
}
class WorkerActor(val guiUpdateActor: ActorRef) extends Actor {
def receive = {
case "Start" => {
for (percentDone <- 0 to 100) {
Thread.sleep(50)
guiUpdateActor ! GuiProgressEvent(percentDone)
}
}
guiUpdateActor ! ProcessingFinished
}
}
}
Source: stackoverflow.com
Related Query
- Asynchronous UI update with Swing
- Using Scala's Swing wrapper, how can I update a panel's contents via foreach with a collection?
- How to update a mongo record using Rogue with MongoCaseClassField when case class contains a scala Enumeration
- Asynchronous IO in Scala with futures
- Update case class from incomplete JSON with Argonaut or Circe
- Interacting with actors in scala swing applications
- scala observable unify observable with a sequence without intermediate datastructure update
- Update a mutable map with default value in Scala
- Implement product type in Scala with generic update function working on its parts
- Slick 3.0.0 - update row with only non-null values
- Multidimensional array declaration fails after update to Eclipse Juno with Scala 2.10
- How to use update output mode with FileFormat format?
- How do I use Swing with Scala 2.11 in Eclipse?
- Mocking database with Slick in ScalaTest + Mockito and testing UPDATE
- Asynchronous message handling with Akka's Actors
- Making a HTTP API server asynchronous with Future, how does it make it non-blocking?
- Update deeply nested case class with Options
- transactions and conditional update in Jooq with scala
- Scala - Update RDD with another Map
- Conditonally UPDATE fields with Slick String interpolation
- asynchronous processing using list of Scala futures with onComplete for exception handling
- Update a dataframe with nested fields - Spark
- How to use futures with Akka for asynchronous results
- Replace Asynchronous Anonymous Class with Function
- How to update Spark dataframe based on Column from other dataframe with many entries in Scala?
- Update Scala Slick rows with optional columns
- How to create Scala swing wrapper classes with SuperMixin?
- Problems with Scala Swing library
- Non-blocking asynchronous mongo java/scala driver can block thread - how to deal with that?
- How to update JSON with arrays of objects?
More Query from same tag
- Slick Json Column Support with MySql
- maven-scala-plugin error running scala code in a Maven project in IntelliJ
- Apache Http Client Put Request Error
- Find and replace not working - dataframe spark scala
- Generate random date in specific range in spark scala
- Tail Recursion Vs. Refactoring
- Scala case class arguments instantiation from array
- Eclipse scala-ide won't start after installing Mac OS X Sierra (Mac OS 10.12)
- How to count documents with query in ReactiveMongo with Play's JSON library?
- How to define function accepting curried function parameter?
- How to check if a given String is an English word in Scala?
- Why is Cassandra client failing without epoll in production?
- Scala Some, None and my custom Default
- How can I fill a string with a character up to the exact length?
- Scala: How to define a method that returns a instance of subclass
- Indexing/Slicing of Collections in Scala
- How to set XLang in Leon online system,Is it possible?
- What's the meaning of #:: in Scala?
- Passing parameters to scalameta paradise macro
- How can I consume paginated resource using Monix in Scala?
- Continuation-passing style in Scala
- Scala equivalent of angular's pretty filter
- An elegant way of creating a Scala sequence that comprises lagged tuples
- EsHadoopIllegalArgumentException: Cannot detect ES version Spark-ElasticSearch example
- How can I connect to a postgreSQL database in scala?
- spark implicit encoder not found in scope
- Why do overridden variables get the wrong values in Scala?
- Spark streaming is not working in Standalone cluster deployed in VM
- scala - process string parsed from gatling EL expression in place with anonymous function
- sbt command not found