加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用Swing进行异步UI更新

发布时间:2020-12-16 18:32:21 所属栏目:安全 来源:网络整理
导读:我写了一个 Scala程序,我希望通过UI(也在Swing中)触发.问题是,当我触发它时,UI会挂起,直到后台程序完成.我认为解决这个问题的唯一方法是让程序在另一个线程/ actor中运行,并在需要时让它更新UI.更新将包括一个状态栏,显示当前正在处理的文件和进度条. 由于Sc
我写了一个 Scala程序,我希望通过UI(也在Swing中)触发.问题是,当我触发它时,UI会挂起,直到后台程序完成.我认为解决这个问题的唯一方法是让程序在另一个线程/ actor中运行,并在需要时让它更新UI.更新将包括一个状态栏,显示当前正在处理的文件和进度条.

由于Scala演员已被弃用,我现在很难通过Akka来进行某种基本的多线程运行. Akka网站上给出的例子也很复杂.

但更重要的是,我发现很难绕过如何尝试这个问题.我能想到的是:

>后台程序作为一个演员运行
> UI是主程序
>让另一个演员告诉UI更新某些内容

第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示例似乎已过时,但它们应该给您一个好主意)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读