Swing Akka应用程序的GUI

Swing Akka应用程序的GUI,swing,scala,user-interface,akka,actor,Swing,Scala,User Interface,Akka,Actor,我在Akka中制作了一个小应用程序,它有一个参与者的层次结构(有一个ActorA有几个ActorB参与者,这些ActorB参与者有几个ActorC参与者)。现在我想添加一个小UI。这个UI没有任何按钮,只有一些标签,当ActorC参与者从其他参与者接收到某些消息时,这些标签会被修改。我的问题是,我必须为每个ActorC参与者创建一个标签,但是ActorC参与者的数量并不总是相同的,所以我必须首先创建ActorC参与者,然后我必须创建标签。我搜索了有关Scala Swing的教程,但我只找到了旧文

我在Akka中制作了一个小应用程序,它有一个参与者的层次结构(有一个ActorA有几个ActorB参与者,这些ActorB参与者有几个ActorC参与者)。现在我想添加一个小UI。这个UI没有任何按钮,只有一些标签,当ActorC参与者从其他参与者接收到某些消息时,这些标签会被修改。我的问题是,我必须为每个ActorC参与者创建一个标签,但是ActorC参与者的数量并不总是相同的,所以我必须首先创建ActorC参与者,然后我必须创建标签。我搜索了有关Scala Swing的教程,但我只找到了旧文档或简单示例,它们在我的案例中并不有用(比如按下按钮做某事)。我甚至看到一些人在他们的Akka应用程序中使用JavaSwing。我找到了一个名为Kamon的工具,但我需要创建一个接口,而不仅仅是监视我的参与者。有人能帮我吗?

Swing不赞成使用JavaFX。也就是说,JavaFX允许您创建一个“富客户端”应用程序。对于你想要的东西来说,这听起来太难了


也许是一个简单的web UI?你看过playframework.com了吗?您的界面将只是一些可以与参与者对话的网页。Play和Akka配合得很好,使用可用的教程和模板很容易开始Play。

您的设计有两个方面。第一个方面是UI和工作参与者之间的通信。第二个是UI的操作

一种情况可能是UI启动并启动Swing EDT线程以显示状态窗口。一个演员也被创造出来,它向你的演员A伸出手,说“准备出发”。参与者A将消息转发给所有参与者B,后者将消息转发给参与者Cs。然后,每个参与者C通过发送消息“我在这里”和“这是我的状态”向UI注册自己

UI参与者获取每个注册消息并将其映射到一个标签,如果需要的话创建它。当每个Actor C改变其状态时,它会向UI Actor发送一条新消息,说“我仍然在这里”和“这是我的状态”

UI参与者是Akka世界和UI之间的中间人。这是一个棘手的部分,因为UI参与者运行在与Swing事件调度线程不同的线程上。它必须将任务放在Swing队列上,以便Swing线程以线程安全的方式进行处理。一些粗略的代码:

// assume labelMap is a map from ActorRef to Label, ordered by insertion
def receive = {
  case IAmHere(status) =>
    val actorC = sender
    if ( ! (labelMap contains actorA) ) {
      addStatusLabel(actorC, status)
    }
  case IAmStillHere(status) =>
    updateStatusLabel(actorC, status)
}
def addStatusLabel(actorC: ActorRef, status: String) = {
  Swing.onEDT {
    labelMap(actorC) = new Label(status)
    // recalculate the panel size
    // repaint
  }
}
def updateStatusLabel(actorC: ActorRef, status: String) = {
  Swing.onEDT {
    labelMap(actorC).text = status
    // repaint
  }
}

我让您来布置UI、容器、状态是否为
String
s、如何处理丢失的Actor Cs等。

您能提供更多上下文吗?akka是在服务器上运行还是看起来更像桌面应用程序?您可能想了解一下如何提供一个Web服务,您可以插入任何可以处理http请求的UI
// assume labelMap is a map from ActorRef to Label, ordered by insertion
def receive = {
  case IAmHere(status) =>
    val actorC = sender
    if ( ! (labelMap contains actorA) ) {
      addStatusLabel(actorC, status)
    }
  case IAmStillHere(status) =>
    updateStatusLabel(actorC, status)
}
def addStatusLabel(actorC: ActorRef, status: String) = {
  Swing.onEDT {
    labelMap(actorC) = new Label(status)
    // recalculate the panel size
    // repaint
  }
}
def updateStatusLabel(actorC: ActorRef, status: String) = {
  Swing.onEDT {
    labelMap(actorC).text = status
    // repaint
  }
}