Scala Popup Menu

How to make a popup appear in Scala? I have a backdoor, but for me it looks pretty ugly:

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)
+3
source share
2 answers

What you do is fine, but if you want to hide the peer-to-peer call, you can 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 as follows:

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

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

Alternatively, you can try SQUIB (Scala Quirky User Interface Builder). Using SQUIB code above:

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

I know that the question is two years old, but I think it is worth updating with another answer. Here is 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 an example 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 notes:

  • SuperMixin, scala -swing-design.pdf, " Wrappers", " -".
  • Mixin scala.swing.SequentialContainer.Wrapper, contents +=, scala -swing Menu.
  • JPopupMenu.setVisible, , JPopupMenu.show, . ( , , .)
+6

All Articles