Suitable GUI framework for Scala?

Solution 1:

Scala has its own Swing library. This will use the standard Swing library under the hood but it has some nice additions and most notably, because it's made for Scala, it can be used in a much more concise way than the standard Swing library:

import swing._

object HelloWorld extends SimpleSwingApplication {
  def top = new MainFrame {
    title = "Hello, World!"
    contents = new Button {
      text = "Click Me!"
    }
  }
}

See how nice and easy it is to set widget properties?

Except for the nicer syntax and the small additions (like the SimpleSwingApplication class), I think the advantages and disadvantages are pretty much the same as with vanilla Swing.

Here's an Overview of Scala Swing.

Solution 2:

ScalaFX is a mature wrapper around JavaFX 2. It is superficially similar to Scala Swing in some regards, but has some features that make it stand out:

  • Couplings to native graphics libraries - This means access to hardware acceleration and other goodies, but requires the JavaFX runtime to be installed on the system. It is included in most major distributions of Java 8. This also means it renders very well on the systems with which it's compatible.

  • Property bindings - This is the killer feature for me. Say that I have three elements: A, B, and C. A and B are resizable, and C is supposed to have a height which is the sum of the heights of A and B at all times. In Swing, this would involve writing a set of custom event listeners to perform this work. ScalaFX bindings lets you express this simply by using the property bind operator: C.height <== A.height + B.height. This, among other features, makes for a very Scala-idiomatic feel.

  • JavaFX Scene Builder (in beta as of writing) is a WYSIWYG GUI editor (I haven't tried it, though).

  • Documentation is its weak point. Being a wrapper, it often refers back to the JavaFX documentation.

Solution 3:

I use Java Swing. Here's how it stacks up against your requirements:

  • mature and used extensively: yes, a ton.

  • rich widget set and renders well: this is debatable. When you consider the ability to easily supplement Java Swing with additional libraries (eg SwingX), it at least does better than Scala Swing in this regard, though probably not as well as some other Java toolkits (though I can't speak to those).

  • idiomatic Scala: not as bad as you might think. A few helper functions make it better:

    implicit class And[A](a: A) {
      def and(f: A => Unit): A = {
        f(a); a
      }
    }
    

    So that you can do

    val button = (new JButton("Press me!")
        and (_ setForeground Color.red)
        and (_ setFont new Font(null, Font.PLAIN, 12)))
    
    val win = (new JFrame("Hello!")
      and (_ add button)
      and (_ pack())
      and (_ setDefaultCloseOperation JFrame.EXIT_ON_CLOSE)
      and (_ setVisible(true)))
    

    Now as for events and state, this is still, in my opinion, a rough edge in all gui frameworks -- listeners have their problems, event streams have their problems. I have had general success in augmenting Swing's events with reactive-core and redo-signals (my own, undocumented) in order to make it easier to organize state.

    You can improve the verbosity of defining listeners with a few more helper functions like

      def actionListener(f: => Unit) = new ActionListener {
        def actionPerformed(e: ActionEvent) { f }
      }
    

    and

      def later(thing: => Unit) {
        SwingUtilities.invokeLater(new Runnable {
          def run() {
            thing
          }
        })
      }
    

    Personally, I wish Scala Swing had taken this route. Writing wrappers for existing Java classes is O(n) programmer time, and doesn't get you anything for the classes that the authors didn't choose to write wrappers for. Creating generic syntactic sugar will take you much farther faster.

  • Got a WYSIWYG-ish but flexible GUI builder: I use IntelliJ IDEA forms, to make an abstract class, and then subclass it with a Scala class. The organizational cost is only 1 extra file, and I write no Java code.

  • Standalone API documentation: Yes.