使用Swing进行异步UI更新
我写了一个
Scala程序,我希望通过UI(也在Swing中)触发.问题是,当我触发它时,UI会挂起,直到后台程序完成.我认为解决这个问题的唯一方法是让程序在另一个线程/ actor中运行,并在需要时让它更新UI.更新将包括一个状态栏,显示当前正在处理的文件和进度条.
由于Scala演员已被弃用,我现在很难通过Akka来进行某种基本的多线程运行. Akka网站上给出的例子也很复杂. 但更重要的是,我发现很难绕过如何尝试这个问题.我能想到的是: >后台程序作为一个演员运行 第3步让我感到困惑.如何在不锁定某个变量的情况下告诉UI? 此外,我确信这个问题已经解决了.任何示例代码都将受到高度赞赏. ======================= 编辑:什么对我有用 我没有使用Actors,而是使用类似于pagoda_5b在他的回答中解释的方式: 将状态栏和进度条移出def def并使其成为全局变量: object MyGUIProject extends SimpleSwingApplication { val txtStatus = new Label //Global val progressBar = new ProgressBar //Global def top = new MainFrame { ... } } 单击按钮后,将来调用后台进程: val btnStart = new Button { text = "Click me to start" reactions += { case ButtonClicked(_) => { val myFuture = future { doLongBackgroundProcess(someString) } myFuture onSuccess { case _ => Swing.onEDT { txtStatus.text = "Done" } } } } } 使用future和Swing.onEDT在后台进程中更新它们: def updateStatus(txt: String) = { val fut = future { Swing.onEDT { txtStatus.text = txt } } } def doLongBackgroundProcess(str:String) = { val taskList = getTasks(str) taskList foreach {x=> updateStatus("Currently doing task: " + x) //Start doing it } } 解决方法
对于scala 2.10
您可以使用scala.concurrent.future,然后在完成时注册回调.回调将更新EDT线程上的GUI. 我们开始做吧! //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 } } 这是最简单的情况: >我们只在完成后更新,没有进展 要处理(1)你可以使用Future实例上的map / flatMap方法组合不同的未来.当调用它们时,您可以更新UI中的进度(始终确保在Swing.onEDT块中执行此操作) //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 } } 要处理(2)你可以在onFailure上注册回调或用onComplete处理这两种情况. 相关示例:scaladocs和相关的SIP(虽然SIP示例似乎已过时,但它们应该给您一个好主意) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |