If you ever wanted to see how easy it is to create a form using the JGoodies FormLayout, this code shows a simple example:
/**
* the "input panel" that goes in the North section of the Sarah3 mainframe BorderLayout.
*/
private def buildInputPanel: JPanel = {
val layout = new FormLayout(
// label textfield
// ----- ---------
"3px, 48px, 8px, pref:grow, 2dlu", //columns
// ----- ---------
"3dlu, p, 3dlu" //rows
)
val builder = new PanelBuilder(layout)
builder.setDefaultDialogBorder
val cc = new CellConstraints
builder.add(statusLabel, cc.xy(2,2))
builder.add(inputField, cc.xy(4,2))
builder.getPanel
}
That code builds the JPanel that’s shown at the top of this image, including the traffic light and wide textfield:

I describe more about how to use the JGoodies form layout PanelBuilder in this tutorial, “Getting Java Swing components to grow and fill using JGoodies FormLayout.”
As one word of caution, this code is based on an old version of the JGoodies FormLayout class. I haven’t learned their newer classes, and I don’t know if this will work with their latest releases.
The complete source code
If it helps to see that panel-building in the context of the complete class, here’s the source code for the current Sarah3 JFrame:
package com.devdaily.sarah.gui
import javax.swing._
import java.awt._
import com.jgoodies.forms.layout.FormLayout
import com.jgoodies.forms.builder.PanelBuilder
import com.jgoodies.forms.layout.CellConstraints
trait StatusIndicator
case object RedLight extends StatusIndicator
case object YellowLight extends StatusIndicator
case object GreenLight extends StatusIndicator
case object NeutralLight extends StatusIndicator
class MainFrame3 extends JFrame {
import SwingUtils.invokeLater
// status icon images
val trafficLightRed = new ImageIcon(classOf[MainFrame3].getResource("trafficLightRedSmall.jpg"))
val trafficLightYellow = new ImageIcon(classOf[MainFrame3].getResource("trafficLightYellowSmall.jpg"))
val trafficLightGreen = new ImageIcon(classOf[MainFrame3].getResource("trafficLightGreenSmall.jpg"))
val trafficLightNeutral = new ImageIcon(classOf[MainFrame3].getResource("trafficLightNeutralSmall.jpg"))
setLayout(new BorderLayout)
// input area
val statusLabel = new JLabel
val inputField = new JTextField
statusLabel.setIcon(trafficLightNeutral)
val inputPanel = buildInputPanel
// output area
val outputArea = new JEditorPane
val scrollPane = new JScrollPane(outputArea)
configureInputField
configureOutputArea
getContentPane.add(inputPanel, BorderLayout.NORTH)
getContentPane.add(scrollPane, BorderLayout.CENTER)
def setStatusIndicator(status: StatusIndicator): Unit = status match {
case RedLight => invokeLater(statusLabel.setIcon(trafficLightRed))
case YellowLight => invokeLater(statusLabel.setIcon(trafficLightYellow))
case GreenLight => invokeLater(statusLabel.setIcon(trafficLightGreen))
case NeutralLight => invokeLater(statusLabel.setIcon(trafficLightNeutral))
}
/**
* the "input panel" that goes in the North section of the Sarah3 mainframe BorderLayout.
*/
private def buildInputPanel: JPanel = {
val layout = new FormLayout(
// label textfield
// ----- ---------
"3px, 48px, 8px, pref:grow, 2dlu", //columns
// ----- ---------
"3dlu, p, 3dlu" //rows
)
val builder = new PanelBuilder(layout)
builder.setDefaultDialogBorder
val cc = new CellConstraints
builder.add(statusLabel, cc.xy(2, 2))
builder.add(inputField, cc.xy(4, 2))
builder.getPanel
}
private def configureOutputArea {
outputArea.setEditable(false)
outputArea.setFont(inputField.getFont.deriveFont(20.0f))
outputArea.setBackground(new Color(230, 230, 230))
outputArea.setMargin(new Insets(20, 20, 20, 20))
outputArea.setText("Welcome to Sarah III")
}
private def configureInputField {
inputField.setFont(inputField.getFont.deriveFont(24.0f));
inputField.setBorder(BorderFactory.createCompoundBorder(inputField.getBorder, BorderFactory.createEmptyBorder(5, 12, 5, 5)))
inputField.setBounds(20, 20, inputField.getHeight, inputField.getWidth)
inputField.setBackground(new Color(250, 250, 250))
}
def setFocusInTextField {
val mainFrame = this
invokeLater(new Runnable {
def run {
mainFrame.requestFocusInWindow
inputField.requestFocusInWindow
Thread.sleep(500)
}
})
}
}
I don’t have time to explain that code, but I hope it makes sense when you can see it along with the JFrame image I shared above.

