如何使用SuperMixin创建Scala swing包装器类?

时间:2014-02-12 12:10:57

标签: swing scala mixins traits

我正在尝试从这个帖子的答案中理解以下类是如何工作的: Scala Popup Menu

由于线程很老,我决定开始一个新问题。我是Scala的新手,有Java背景,我想知道这个类是如何工作的。我读到一个与类同名的对象就像一个带有单例对象的类?我不确定这对于实现包装器是否适合..(为什么我们需要对象?)

SuperMixin的特质究竟是什么? API说“这个特性用于将来自对等体的某些调用重定向到包装器并返回。用于公开可以通过覆盖自定义的方法。”这对初学者的解释不是很好。

如果有人可以帮助向初学者解释这个类和对象(在我看来,神奇地)让我成为JPopupMenu的包装类并让我调用show方法使popupMenu出现,我真的很感激。屏幕..而且似乎我可以设置其内容(内容+ =一些scala.swing.menuItem)而不在下面的类中定义它?

import javax.swing.JPopupMenu
import scala.swing.{ Component, MenuItem }
import scala.swing.SequentialContainer.Wrapper

object PopupMenu {
  private[PopupMenu] trait JPopupMenuMixin { def popupMenuWrapper: PopupMenu }
}

class PopupMenu extends Component with Wrapper {

  override lazy val peer: JPopupMenu = new JPopupMenu with PopupMenu.JPopupMenuMixin with SuperMixin {
    def popupMenuWrapper = PopupMenu.this
  }

  def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y)

  /* Create any other peer methods here */
}

1 个答案:

答案 0 :(得分:2)

PopupMenu伴随对象除了作为辅助特征JPopupMenuMixin的名称空间之外,在此处没有任何特定用途。然后可以通过将其设为private[PopupMenu]来“隐藏”此特征,因此只有类PopupMenu及其伴随对象才能知道它。

坦率地说,我没有看到这个特性的目的。它定义了一个指向外部Scala Swing组件的方法popupMenuWrapper,但根本不使用该方法。所以一个不那么令人困惑的版本就是:

import scala.swing._
import javax.swing.JPopupMenu

class PopupMenu extends Component with SequentialContainer.Wrapper {
  override lazy val peer: JPopupMenu = new JPopupMenu with SuperMixin

  def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y)
}

测试:

val pop = new PopupMenu {
  contents += new MenuItem("Foo")
}
lazy val but: Button = Button("Test") {
  pop.show(but, 0, 0)
}
val f = new Frame {
  contents = but
  pack().centerOnScreen()
  open()
}

包装器唯一需要的是扩展scala.swing.Component并覆盖基础peer组件的javax.swing值。该组件的mixin with SuperMixin overrides a few methods,例如paintComponent,以便将它们转发到外部包装器组件。就是这样。

包装器混合在SequentialContainer.Wrapper中,允许contents +=操作添加菜单项。