The contents of a scala.swing.Frame or scala.swing.MainFrame object is a single component. Typically, we want to show more things in a window than just a single label or a single button. That means that we have to worry about laying out multiple components.
Our next program, gui3.scala, uses a scala.swing.BoxPanel to arrange multiple components inside the window. So the window's (MainFrame's) contents is a BoxPanel, and the BoxPanel contains a label and two buttons:
import scala.swing._
class UI extends MainFrame {
title = "GUI Program #3"
contents = new BoxPanel(Orientation.Vertical) {
contents += new Label("Look at me!")
contents += Button("Press me, please") { println("Thank you") }
contents += Button("Close") { sys.exit(0) }
}
}
object GuiProgramThree {
def main(args: Array[String]) {
val ui = new UI
ui.visible = true
}
}
The assignment
contents = new BoxPanel(Orientation.Vertical) {
contents += new Label("Look at me!")
contents += Button("Press me, please") { println("Thank you") }
contents += Button("Close") { sys.exit(0) }
}
creates a new object of a class that extends BoxPanel. The
three lines that add a label and two buttons to the contents of this
object form the constructor of this nameless class. We could instead
have written the UI class like this:
class UI extends MainFrame {
title = "GUI Program #3"
val box = new BoxPanel(Orientation.Vertical)
box.contents += new Label("Look at me!")
box.contents += Button("Press me, please") { println("Thank you") }
box.contents += Button("Close") { sys.exit(0) }
contents = box
}
However, this style is less common in Scala.
The window looks like this:
If you change Orientation.Vertical to Orientation.Horizontal, the window will look like this:
class UI extends MainFrame {
title = "GUI Program #3"
contents = new BoxPanel(Orientation.Vertical) {
contents += new Label("Look at me!")
contents += Button("Press me, please") { println("Thank you") }
contents += Button("Close") { sys.exit(0) }
border = Swing.EmptyBorder(10, 10, 10, 10)
}
}
It will look like this (the four numbers indicate the top, left,
right, and bottom border width in pixels):
border = Swing.BeveledBorder(Swing.Lowered)
border = Swing.BeveledBorder(Swing.Raised)
border = Swing.MatteBorder(10, 10, 10, 10, java.awt.Color.WHITE)
border = Swing.TitledBorder(Swing.LineBorder(java.awt.Color.RED), "Fun")
border = Swing.TitledBorder(Swing.EtchedBorder(Swing.Lowered), "Fun")
border = Swing.CompoundBorder(Swing.BeveledBorder(Swing.Lowered),
Swing.EmptyBorder(10, 10, 10, 10))
You can find pictures of these borders on the Java
website.
The buttons are still too close together. Also, what happens when you resize?
class UI extends MainFrame {
title = "GUI Program #3"
contents = new BoxPanel(Orientation.Vertical) {
contents += new Label("Look at me!")
contents += Swing.VStrut(10)
contents += Swing.Glue
contents += Button("Press me, please") { println("Thank you") }
contents += Swing.VStrut(5)
contents += Button("Close") { sys.exit(0) }
border = Swing.EmptyBorder(10, 10, 10, 10)
}
}
We only discussed the BoxPanel here, but there are other useful panels that layout their elements in a different way: FlowPanel, BorderPanel, GridPanel, and GridBagPanel.