Search code examples
scalascala-swing

Can I create GUI without "extends"


I start to learn Scala and I confused. Can I create GUI without "extends SimpleSwingApplication" or "SimpleGUIApplication" or may be something yet? I try to do it so:

import scala.swing._

object Main {
def main(args:Array[String]): Unit = {
    val frame = new Frame   {title = "test GUI"}
    val button = new Button {text = "test button"}
    val uslPanel = new BoxPanel(Orientation.Vertical) {
        contents += button
        }
    //listenTo(button)

    frame.contents_=(uslPanel)
    frame.visible_=(true)
    }
}

It works, but if only "listenTo(botton)" is commented. How can I use "listenTo(...)" without "extends SimpleGui... etc".


Solution

  • Two things that the swing application traits give you. (1) they defer the initial code to the event dispatch thread (cf. Swing's Threading Policy, also here). (2) They inherit the Reactor trait which gives you the listenTo method that you are now missing.

    I think you should just mix in the SwingApplication application trait, that's the easiest. Otherwise, you can do these things by hand:

    import scala.swing._
    
    object Main {
      def main(args: Array[String]) {
        Swing.onEDT(initGUI) // Scala equivalent of Java's SwingUtilities.invokeLater
      }
    
      def initGUI() {
        val frame  = new Frame  { title = "test GUI"    }
        val button = new Button { text  = "test button" }
        val uslPanel = new BoxPanel(Orientation.Vertical) {
          contents += button
        }
        val r = new Reactor {}
        r.listenTo(button)
        r.reactions += {
          case event.ButtonClicked(_) => println("Clicked")
        }
    
        frame.contents = uslPanel
        frame.visible  = true  // or use `frame.open()`
      }
    }
    

    Note that every widget in Scala-Swing inherits Reactor, so you often find this style:

        val button = new Button {
          text = "test button"
          listenTo(this) // `listenTo` is defined on Button because Button is a Reactor
          reactions += { // `reactions` as well
            case event.ButtonClicked(_) => println("Clicked")
          }
        }