Scala Popup Menu

梦想的初衷 提交于 2019-11-27 06:24:31

问题


How do I cause a popup to get shown in Scala? I have a "backdoor" but it seems pretty ugly to me:

val item = new MenuItem(new Action("Say Hello") {
  def apply = println("Hello World");
})
//SO FAR SO GOOD, NOW FOR THE UGLY BIT!
val popup = new javax.swing.JPopupMenu
popup.add(item.peer)
popup.setVisible(true)

回答1:


What you are doing is fine, but if you'd like to hide the peer call you could create your own class:

class PopupMenu extends Component
{
  override lazy val peer : JPopupMenu = new JPopupMenu

  def add(item:MenuItem) : Unit = { peer.add(item.peer) }
  def setVisible(visible:Boolean) : Unit = { peer.setVisible(visible) }
  /* Create any other peer methods here */
}

Then you can use it like this:

val item = new MenuItem(new Action("Say Hello") {
  def apply = println("Hello World");
})

val popup = new PopupMenu
popup.add(item)
popup.setVisible(true)

As an alternative, you could try SQUIB (Scala's Quirky User Interface Builder). With SQUIB, the above code becomes:

popup(
  contents(
    menuitem(
      'text -> "Say Hello",
      actionPerformed(
        println("Hello World!")
      )
    )
  )
).setVisible(true)



回答2:


I know the question is two years old, but I think it's worth updating with another answer. Here's my solution:

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 */
}

Here is some sample usage code:

val popupMenu = new PopupMenu {
  contents += new Menu("menu 1") {
    contents += new RadioMenuItem("radio 1.1")
    contents += new RadioMenuItem("radio 1.2")
  }
  contents += new Menu("menu 2") {
    contents += new RadioMenuItem("radio 2.1")
    contents += new RadioMenuItem("radio 2.2")
  }
}
val button = new Button("Show Popup Menu")
reactions += {
  case e: ButtonClicked => popupMenu.show(button, 0, button.bounds.height)
}
listenTo(button)

Some things to note:

  1. Use of SuperMixin class as recommended in scala-swing-design.pdf, in section "Guidelines for Writing Wrappers", subsection "Use the wrapper cache".
  2. Mixin scala.swing.SequentialContainer.Wrapper so that I can use the contents += construct so my Popup Menu code looks like other scala-swing Menu construction code.
  3. While the question uses JPopupMenu.setVisible, I think you are going to want to wrap and use the method JPopupMenu.show, so you can control the location of the Popup Menu. (Just setting it to be visible puts it in the top left-hand corner of the screen for me.)


来源:https://stackoverflow.com/questions/938753/scala-popup-menu

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!