使用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示例似乎已过时,但它们应该给您一个好主意) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!  | 
                  
