de.sciss.swingplus

GroupPanel

class GroupPanel extends Panel

A panel that uses javax.swing.GroupLayout to visually arrange its components.

Note: This is a slightly adapted variant of the original GroupPanel class by Andreas Flier and which was part of the ScalaSwingContrib project. We thought it was a bit over-engineered, and also some naming was problematic (theHorizontalLayout is ...) and involving reflection-based structural types.

The key point to understanding this layout manager is that it separates horizontal and vertical layout. Thus, every component appears twice: once in the horizontal and once in the vertical layout. Consult the Java API documentation for GroupLayout and Sun's Java tutorials for a comprehensive explanation.

The main advantage of using this panel instead of manually tinkering with the layout is that this panel provides a concise, declarative syntax for laying out its components. This approach should make most use cases easier. In some special cases, e.g. when re-creating layouts on-the-fly, it might be preferable to use a more imperative style, for which direct access to the underlying layout manager is provided.

In contrast to the underlying swing layout, this panel activates the automatic creation of gaps between components by default, since this panel is intended for coding UIs "by hand", not so much for visual UI builder tools. Many features of the underlying layout are aimed at those, tough. Most of them are available through this panel for completeness' sake but it is anticipated that coders won't need to use them very much.

Code examples

This section contains a few simple examples to showcase the basic functionality of GroupPanels. For all examples, it is assumed that everything from the package scala.swing is imported and the code is placed inside a scala.swing.SimpleSwingApplication like this:

import scala.swing._
import de.sciss.swingplus._

object Example extends SimpleSwingApplication {
  lazy val top = new MainFrame {
    contents = new GroupPanel {
      // example code here
    }
  }
}

Simple panel with 2 components

In the first example, there's a label and a text field, which appear in a horizontal sequence but share the same vertical space.

val label     = new Label("Label:")
val textField = new TextField(20)

horizontal    = Seq(label, textField)
vertical      = Par(label, textField)

It can be observed that the resize behaviour of the text field is rather strange. To get better behaviour, the components' vertical sizes can be linked together.

linkVerticalSize(label, textField)

Alternatively, it would have been possible to disallow the resizing of the vertical, parallel group. To achieve this, the vertical layout line should be written this way:

vertical = Par(Leading, FixedSize)(label, textField)

Since text fields aren't resizable when used with baseline alignment (more about that further down), the following code also prevents (vertical) resizing:

vertical = Par(Baseline)(label, textField)

Size and alignment

Components can be added with custom size constraints (minimum, preferred, maximum size). The next example showcases that. The text field appears with a preferred height of 100 pixels and when the component is resized, it can be reduced to its minimum height of 50 pixels and enlarged to its maximum height of 200 pixels.

horizontal = Seq(label, textField)
vertical   = Par(label, Size(textField, 50, 100, 200))

The Size object holds some useful constants: Default, Preferred and Infinite, that can be used for any of the minimum, preferred and maximum arguments.

Instead of using these hints with Size.apply, one can also use the provided convenience methods Size.fixed and Size.fill.

Because the default alignment in a parallel group is Leading, both components are "glued" to the top of the container (panel). To align the label's text with the text inside the text field, an explicit alignment can be specified in a preceding argument list, like this:

horizontal = Seq(label, textField)
vertical   = Par(Baseline)(label, Size(textField, 50, 100, 200))

This example also shows a potential problem of baseline alignment: some components stop being resizable. More specifically, the javadoc for GroupLayout.ParallelGroup states:

Since a text field's resizing behaviour is CENTER_OFFSET, it is not resizable when used with baseline alignment.

Gaps

The GroupPanel turns on automatic creation of gaps between components and along the container edges. To see the difference, try turning this feature off manually by inserting the following lines:

autoGaps          = false
autoContainerGaps = false

With both types of gaps missing, the components are clamped together and to the container edges, which does not look very pleasing. Gaps can be added manually, too. The following example does this in order to get a result that looks similar to the version with automatically created gaps, albeit in a much more verbose manner.

horizontal = Seq(
  Gap.Container(),
  label,
  Gap.Preferred(Related),
  textField,
  Gap.Container()
)

vertical = Seq(
  Gap.Container(),
  Parallel(label, textField),
  Gap.Container()
)

Rigid gaps with custom size or completely manual gaps (specifying minimum, preferred and maximum size) between components are created with the Gap object:

bc.. horizontal = Seq(
  label,
  Gap(10, 20, 100),
  textField
)

vertical = Seq(
  Par(label, Gap(30), textField)
)

In a parallel group, such a gap can be used to specify a minimum amount of space taken by the group.

In addition to rigid gaps in the previous example, it is also possible to specify gaps that resize. This could be done by specifying a maximum size of Infinite. However, for the most commonly used type of these, there is a bit of syntax sugar available with the Spring and ContainerSpring methods.

bc.. horizontal = Seq(
Gap.Container(),
label,
Gap.Spring(), // default is Related
textField,
Gap.ContainerSpring()
)

These create gaps that minimally are as wide as a Gap.Preferred would be - it is possible to specify whether the Related or Unrelated distance should be used - but can be resized to an arbitrary size.

bc.. horizontal = Seq(
Gap.Container(),
label,
Gap.Spring(Unrelated),
textField,
Gap.ContainerSpring()
)

The preferred size can also be specified more closely (Size.Default or Size.Infinite aka "as large as possible"):

bc.. horizontal = Seq(
Gap.Container(),
label,
Gap.Spring(Unrelated, Size.Infinite),
textField,
Gap.ContainerSpring(Size.Infinite)
)

Please note that Gap.Preferred, Spring, Gap.Container and Spring.Container may only be used inside a sequential group.

A dialog with several components

As a last, more sophisticated example, here's the GroupPanel version of the "Find" dialog presented as example for GroupLayout in the Java tutorials by Sun:

val label         = new Label("Find what:")
val textField     = new TextField
val caseCheckBox  = new CheckBox("Match case")
val wholeCheckBox = new CheckBox("Whole words")
val wrapCheckBox  = new CheckBox("Wrap around")
val backCheckBox  = new CheckBox("Search backwards")
val findButton    = new Button("Find")
val cancelButton  = new Button("Cancel")

horizontal = Seq(
  label,
  Par(
    textField,
    Seq(
      Par(caseCheckBox, wholeCheckBox),
      Par(wrapCheckBox, backCheckBox)
    )
  ),
  Par(findButton, cancelButton)
)

linkHorizontalSize(findButton, cancelButton)

vertical = Seq(
  Par(Baseline)(label, textField, findButton),
  Par(
    Seq(
      Par(Baseline)(caseCheckBox, wrapCheckBox),
      Par(Baseline)(wholeCheckBox, backCheckBox)
    ),
    cancelButton
  )
)

Mapping component sequences

Often you will want to build panels from a sequence of components and arrange them in a grid. The Seq.apply and Par.apply methods take a sequence of GroupPanel.Element instances, and therefore you may have to explicitly convert them, as the implicit conversion does not kick in for collections. There are two possibilities, as demonstrated in the last example:

class Param(val check: CheckBox, val label: Label, val slider: Slider, val index: Spinner)

val p1 = new Param(
  new CheckBox,
  new Label("Foo"),
  new Slider { value = 10 },
  new Spinner(new SpinnerNumberModel(10, 0, 100, 1))
)
val p2 = new Param(
  new CheckBox { selected = true },
  new Label("Bar"),
  new Slider,
  new Spinner(new SpinnerNumberModel(50, 0, 100, 1))
)
val params = List(p1, p2)

horizontal = Seq(
  Par(params.map(r => r.check: GroupPanel.Element): _*),
  Par(params.map(r => r.label: GroupPanel.Element): _*),
  new Par { params.foreach(r => contents += r.slider) },
  new Par { params.foreach(r => contents += r.index ) }
)

vertical = Seq(
  params.map { p =>
    Par(Center)(p.check, p.label, p.slider, p.index)
  }: _*
)

As can be seen, the Seq and Par classes can be instantiated and then populated through calls to the contents member.

See also

javax.swing.GroupLayout

Linear Supertypes
Panel, Wrapper, Container, Component, UIElement, scala.swing.LazyPublisher, Publisher, Reactor, Proxy, AnyRef, Any
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. GroupPanel
  2. Panel
  3. Wrapper
  4. Container
  5. Component
  6. UIElement
  7. LazyPublisher
  8. Publisher
  9. Reactor
  10. Proxy
  11. AnyRef
  12. Any
  1. Hide All
  2. Show all
Learn more about member selection
Visibility
  1. Public
  2. All

Instance Constructors

  1. new GroupPanel()

Type Members

  1. class Content extends BufferWrapper[Component]

    Attributes
    protected
    Definition Classes
    Wrapper
  2. class Par extends Group

  3. class Seq extends Group

  4. trait SuperMixin extends JComponent

    Attributes
    protected
    Definition Classes
    Component

Value Members

  1. final def !=(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  2. final def !=(arg0: Any): Boolean

    Definition Classes
    Any
  3. final def ##(): Int

    Definition Classes
    AnyRef → Any
  4. final def ==(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  5. final def ==(arg0: Any): Boolean

    Definition Classes
    Any
  6. def Baseline: Alignment

    Attributes
    protected
  7. def Center: Alignment

    Attributes
    protected
  8. def Gap: GroupPanel.Gap.type

    Attributes
    protected
  9. def Indent: ComponentPlacement

    Attributes
    protected
  10. def Leading: Alignment

    Attributes
    protected
  11. object Par

  12. def Related: ComponentPlacement

    Attributes
    protected
  13. object Seq

  14. def Size: GroupPanel.Size.type

    Attributes
    protected
  15. def Trailing: Alignment

    Attributes
    protected
  16. def Unrelated: ComponentPlacement

    Attributes
    protected
  17. val _contents: Content

    Attributes
    protected
    Definition Classes
    Wrapper
  18. final def asInstanceOf[T0]: T0

    Definition Classes
    Any
  19. def autoContainerGaps: Boolean

    Indicates whether gaps between components and the container borders are automatically created.

  20. def autoContainerGaps_=(value: Boolean): Unit

    Sets whether gaps between components and the container borders are automatically created.

  21. def autoGaps: Boolean

    Indicates whether gaps between components are automatically created.

  22. def autoGaps_=(value: Boolean): Unit

    Sets whether gaps between components are automatically created.

  23. def background: Color

    Definition Classes
    UIElement
  24. def background_=(c: Color): Unit

    Definition Classes
    UIElement
  25. def border: Border

    Definition Classes
    Component
  26. def border_=(b: Border): Unit

    Definition Classes
    Component
  27. def bounds: Rectangle

    Definition Classes
    UIElement
  28. def clone(): AnyRef

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  29. def contents: scala.Seq[Component]

    Definition Classes
    Wrapper → Container
  30. def cursor: Cursor

    Definition Classes
    UIElement
  31. def cursor_=(c: Cursor): Unit

    Definition Classes
    UIElement
  32. def deafTo(ps: Publisher*): Unit

    Definition Classes
    Reactor
  33. def displayable: Boolean

    Definition Classes
    UIElement
  34. def enabled: Boolean

    Definition Classes
    Component
  35. def enabled_=(b: Boolean): Unit

    Definition Classes
    Component
  36. final def eq(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  37. def equals(that: Any): Boolean

    Definition Classes
    Proxy → Any
  38. def finalize(): Unit

    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  39. def focusable: Boolean

    Definition Classes
    Component
  40. def focusable_=(b: Boolean): Unit

    Definition Classes
    Component
  41. def font: Font

    Definition Classes
    UIElement
  42. def font_=(f: Font): Unit

    Definition Classes
    UIElement
  43. def foreground: Color

    Definition Classes
    UIElement
  44. def foreground_=(c: Color): Unit

    Definition Classes
    UIElement
  45. final def getClass(): Class[_]

    Definition Classes
    AnyRef → Any
  46. def hasFocus: Boolean

    Definition Classes
    Component
  47. def hashCode(): Int

    Definition Classes
    Proxy → Any
  48. def honorVisibilityOf(comp: Component): Unit

    The component will not take up any space when it's invisible (default).

  49. def honorsVisibility: Boolean

    Indicates whether the visibility of components is considered for the layout.

    Indicates whether the visibility of components is considered for the layout. If set to false, invisible components still take up space. Defaults to true.

  50. def honorsVisibility_=(value: Boolean): Unit

    Sets whether the visibility of components should be considered for the layout.

    Sets whether the visibility of components should be considered for the layout. If set to false, invisible components still take up space. Defaults to true.

  51. def horizontal: Group

  52. def horizontal_=(value: Group): Unit

  53. def ignoreRepaint: Boolean

    Definition Classes
    UIElement
  54. def ignoreRepaint_=(b: Boolean): Unit

    Definition Classes
    UIElement
  55. def ignoreVisibilityOf(comp: Component): Unit

    The component will still take up its space even when invisible.

  56. var initP: JComponent

    Definition Classes
    Component
  57. def inputVerifier: (Component) ⇒ Boolean

    Definition Classes
    Component
  58. def inputVerifier_=(v: (Component) ⇒ Boolean): Unit

    Definition Classes
    Component
  59. final def isInstanceOf[T0]: Boolean

    Definition Classes
    Any
  60. val layout: GroupLayout

    This panel's underlying layout manager is a GroupLayout instance.

  61. def layoutStyle: LayoutStyle

    Returns the layout style used.

  62. def layoutStyle_=(value: LayoutStyle): Unit

    Assigns a layout style to use.

  63. def linkHorizontalSize(comps: Component*): Unit

    Links the sizes of several components horizontally.

    Links the sizes of several components horizontally.

    comps

    the components to link

  64. def linkSize(comps: Component*): Unit

    Links the sizes (horizontal and vertical) of several components.

    Links the sizes (horizontal and vertical) of several components.

    comps

    the components to link

  65. def linkVerticalSize(comps: Component*): Unit

    Links the sizes of several components vertically.

    Links the sizes of several components vertically.

    comps

    the components to link

  66. def listenTo(ps: Publisher*): Unit

    Definition Classes
    Reactor
  67. val listeners: RefSet[Reaction] { val underlying: scala.collection.mutable.HashSet[scala.ref.Reference[scala.swing.Reactions.Reaction]] }

    Attributes
    protected
    Definition Classes
    Publisher
  68. def locale: Locale

    Definition Classes
    UIElement
  69. def location: Point

    Definition Classes
    UIElement
  70. def locationOnScreen: Point

    Definition Classes
    UIElement
  71. def maximumSize: Dimension

    Definition Classes
    UIElement
  72. def maximumSize_=(x: Dimension): Unit

    Definition Classes
    UIElement
  73. def minimumSize: Dimension

    Definition Classes
    UIElement
  74. def minimumSize_=(x: Dimension): Unit

    Definition Classes
    UIElement
  75. def name: String

    Definition Classes
    Component
  76. def name_=(s: String): Unit

    Definition Classes
    Component
  77. final def ne(arg0: AnyRef): Boolean

    Definition Classes
    AnyRef
  78. final def notify(): Unit

    Definition Classes
    AnyRef
  79. final def notifyAll(): Unit

    Definition Classes
    AnyRef
  80. def onFirstSubscribe(): Unit

    Attributes
    protected
    Definition Classes
    Component → UIElement → LazyPublisher
  81. def onLastUnsubscribe(): Unit

    Attributes
    protected
    Definition Classes
    UIElement → LazyPublisher
  82. def opaque: Boolean

    Definition Classes
    Component
  83. def opaque_=(b: Boolean): Unit

    Definition Classes
    Component
  84. def paint(g: Graphics2D): Unit

    Definition Classes
    Component
  85. def paintBorder(g: Graphics2D): Unit

    Attributes
    protected
    Definition Classes
    Component
  86. def paintChildren(g: Graphics2D): Unit

    Attributes
    protected
    Definition Classes
    Component
  87. def paintComponent(g: Graphics2D): Unit

    Attributes
    protected
    Definition Classes
    Component
  88. lazy val peer: JPanel

    Definition Classes
    Panel → Wrapper → Component → UIElement
  89. def preferredSize: Dimension

    Definition Classes
    UIElement
  90. def preferredSize_=(x: Dimension): Unit

    Definition Classes
    UIElement
  91. def publish(e: Event): Unit

    Definition Classes
    Publisher
  92. val reactions: Reactions

    Definition Classes
    Reactor
  93. def repaint(rect: Rectangle): Unit

    Definition Classes
    UIElement
  94. def repaint(): Unit

    Definition Classes
    UIElement
  95. def replace(existing: Component, replacement: Component): Unit

    Replaces one component with another.

    Replaces one component with another. Useful for dynamic layouts.

    existing

    the component to be replaced

    replacement

    the component replacing the existing one

  96. def requestFocus(): Unit

    Definition Classes
    Component
  97. def requestFocusInWindow(): Boolean

    Definition Classes
    Component
  98. def revalidate(): Unit

    Definition Classes
    Component
  99. def self: Component

    Definition Classes
    UIElement → Proxy
  100. def showing: Boolean

    Definition Classes
    UIElement
  101. def size: Dimension

    Definition Classes
    UIElement
  102. def subscribe(listener: Reaction): Unit

    Definition Classes
    LazyPublisher → Publisher
  103. final def synchronized[T0](arg0: ⇒ T0): T0

    Definition Classes
    AnyRef
  104. def toString(): String

    Definition Classes
    Component → Proxy → AnyRef → Any
  105. def toolkit: Toolkit

    Definition Classes
    UIElement
  106. def tooltip: String

    Definition Classes
    Component
  107. def tooltip_=(t: String): Unit

    Definition Classes
    Component
  108. def unsubscribe(listener: Reaction): Unit

    Definition Classes
    LazyPublisher → Publisher
  109. def vertical: Group

  110. def vertical_=(value: Group): Unit

  111. def visible: Boolean

    Definition Classes
    UIElement
  112. def visible_=(b: Boolean): Unit

    Definition Classes
    UIElement
  113. final def wait(): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  114. final def wait(arg0: Long, arg1: Int): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  115. final def wait(arg0: Long): Unit

    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  116. implicit def wrapPar(c: Component): GroupPanel.Element.Par

    This method is needed for implicit resolution in Scala 2.

    This method is needed for implicit resolution in Scala 2.10 due to some bug (?). It is not needed any more for Scala 2.11

    Attributes
    protected
  117. implicit def wrapSeq(c: Component): GroupPanel.Element.Seq

    This method is needed for implicit resolution in Scala 2.

    This method is needed for implicit resolution in Scala 2.10 due to some bug (?). It is not needed any more for Scala 2.11

    Attributes
    protected
  118. def xLayoutAlignment: Double

    Definition Classes
    Component
  119. def xLayoutAlignment_=(x: Double): Unit

    Definition Classes
    Component
  120. def yLayoutAlignment: Double

    Definition Classes
    Component
  121. def yLayoutAlignment_=(y: Double): Unit

    Definition Classes
    Component

Inherited from Panel

Inherited from Wrapper

Inherited from Container

Inherited from Component

Inherited from UIElement

Inherited from scala.swing.LazyPublisher

Inherited from Publisher

Inherited from Reactor

Inherited from Proxy

Inherited from AnyRef

Inherited from Any

Ungrouped