CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-codehaus-groovy--groovy-all

Apache Groovy - A powerful multi-faceted programming language for the JVM platform with comprehensive module support

Pending
Overview
Eval results
Files

swing.mddocs/

Swing UI Building

Groovy provides powerful Swing integration through SwingBuilder, enabling declarative GUI construction with a fluent, builder-pattern API that simplifies desktop application development.

SwingBuilder

Core Builder Class

class SwingBuilder extends FactoryBuilderSupport {
    SwingBuilder()
    SwingBuilder(boolean init)
    
    Object invokeMethod(String name, Object args)
    
    // Container methods
    JFrame frame(Map attributes, Closure content)
    JFrame frame(Closure content)
    JDialog dialog(Map attributes, Closure content)
    JPanel panel(Map attributes, Closure content)
    JScrollPane scrollPane(Map attributes, Closure content)
    JSplitPane splitPane(Map attributes, Closure content)
    JTabbedPane tabbedPane(Map attributes, Closure content)
    
    // Control methods
    JButton button(Map attributes, Closure content)
    JLabel label(Map attributes, Closure content)
    JTextField textField(Map attributes)
    JTextArea textArea(Map attributes)
    JCheckBox checkBox(Map attributes)
    JRadioButton radioButton(Map attributes)
    JComboBox comboBox(Map attributes)
    JList list(Map attributes)
    JTable table(Map attributes)
    JTree tree(Map attributes)
    
    // Menu methods
    JMenuBar menuBar(Map attributes, Closure content)
    JMenu menu(Map attributes, Closure content)
    JMenuItem menuItem(Map attributes, Closure content)
    JPopupMenu popupMenu(Map attributes, Closure content)
    
    // Layout methods
    Object borderLayout(Map attributes)
    Object flowLayout(Map attributes)
    Object gridLayout(Map attributes)
    Object gridBagLayout(Map attributes)
    Object cardLayout(Map attributes)
    Object boxLayout(Map attributes)
    
    // Action methods
    Action action(Map attributes, Closure closure)
    void bind(Map attributes)
    
    // Event handling
    void edt(Closure closure)
    void doLater(Closure closure)
    void doOutside(Closure closure)
}

Basic GUI Components

Simple Window Creation

import groovy.swing.SwingBuilder
import javax.swing.WindowConstants

def swing = new SwingBuilder()

def frame = swing.frame(
    title: 'My Application',
    size: [400, 300],
    locationRelativeTo: null,
    defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE
) {
    panel {
        label(text: 'Hello, Swing!')
        button(text: 'Click Me', actionPerformed: { 
            println 'Button clicked!' 
        })
    }
}

frame.setVisible(true)

Layout Management

import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import java.awt.FlowLayout
import java.awt.GridLayout

def swing = new SwingBuilder()

def frame = swing.frame(title: 'Layout Examples', size: [500, 400]) {
    // BorderLayout example
    borderLayout()
    
    panel(constraints: BorderLayout.NORTH) {
        flowLayout()
        label(text: 'North Panel')
        button(text: 'Button 1')
        button(text: 'Button 2')
    }
    
    panel(constraints: BorderLayout.CENTER) {
        gridLayout(rows: 2, cols: 2, hgap: 5, vgap: 5)
        button(text: 'Grid 1')
        button(text: 'Grid 2') 
        button(text: 'Grid 3')
        button(text: 'Grid 4')
    }
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout(alignment: FlowLayout.RIGHT)
        button(text: 'OK')
        button(text: 'Cancel')
    }
}

frame.setVisible(true)

Input Controls

import groovy.swing.SwingBuilder
import javax.swing.border.TitledBorder

def swing = new SwingBuilder()
def model = [name: '', age: 0, subscribed: false, category: 'Bronze']

def frame = swing.frame(title: 'Input Form', size: [400, 300]) {
    borderLayout()
    
    panel(constraints: BorderLayout.CENTER, border: new TitledBorder('User Information')) {
        gridBagLayout()
        
        label(text: 'Name:', constraints: gbc(gridx: 0, gridy: 0, anchor: WEST))
        textField(
            columns: 20,
            constraints: gbc(gridx: 1, gridy: 0, fill: HORIZONTAL),
            text: bind(source: model, sourceProperty: 'name', mutual: true)
        )
        
        label(text: 'Age:', constraints: gbc(gridx: 0, gridy: 1, anchor: WEST))
        spinner(
            model: spinnerNumberModel(value: 18, minimum: 0, maximum: 120),
            constraints: gbc(gridx: 1, gridy: 1),
            stateChanged: { e -> model.age = e.source.value }
        )
        
        checkBox(
            text: 'Subscribe to newsletter',
            constraints: gbc(gridx: 0, gridy: 2, gridwidth: 2),
            selected: bind(source: model, sourceProperty: 'subscribed', mutual: true)
        )
        
        label(text: 'Category:', constraints: gbc(gridx: 0, gridy: 3, anchor: WEST))
        comboBox(
            items: ['Bronze', 'Silver', 'Gold', 'Platinum'],
            constraints: gbc(gridx: 1, gridy: 3),
            selectedItem: bind(source: model, sourceProperty: 'category', mutual: true)
        )
    }
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout()
        button(text: 'Submit', actionPerformed: {
            println "Name: ${model.name}"
            println "Age: ${model.age}"
            println "Subscribed: ${model.subscribed}"
            println "Category: ${model.category}"
        })
        button(text: 'Reset', actionPerformed: {
            model.name = ''
            model.age = 18
            model.subscribed = false
            model.category = 'Bronze'
        })
    }
}

frame.setVisible(true)

Advanced Components

Table with Data

import groovy.swing.SwingBuilder
import javax.swing.table.DefaultTableModel

def swing = new SwingBuilder()

// Sample data
def data = [
    ['John Doe', 30, 'Engineering', 75000],
    ['Jane Smith', 25, 'Marketing', 65000],
    ['Bob Johnson', 35, 'Sales', 70000],
    ['Alice Brown', 28, 'Engineering', 80000]
]

def columnNames = ['Name', 'Age', 'Department', 'Salary']
def tableModel = new DefaultTableModel(data as Object[][], columnNames as Object[])

def frame = swing.frame(title: 'Employee Table', size: [600, 400]) {
    borderLayout()
    
    scrollPane(constraints: BorderLayout.CENTER) {
        table(
            model: tableModel,
            selectionMode: SINGLE_SELECTION,
            mouseClicked: { e ->
                if (e.clickCount == 2) {
                    def table = e.source
                    def row = table.selectedRow
                    if (row >= 0) {
                        def name = tableModel.getValueAt(row, 0)
                        swing.optionPane().showMessageDialog(
                            frame, 
                            "Selected employee: $name",
                            'Selection',
                            swing.optionPane.INFORMATION_MESSAGE
                        )
                    }
                }
            }
        )
    }
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout()
        button(text: 'Add Employee', actionPerformed: {
            def name = swing.optionPane().showInputDialog('Enter name:')
            if (name) {
                tableModel.addRow(['New Employee', 25, 'Department', 50000] as Object[])
            }
        })
        button(text: 'Remove Selected', actionPerformed: {
            def table = frame.contentPane.getComponent(0).viewport.view
            def selectedRow = table.selectedRow
            if (selectedRow >= 0) {
                tableModel.removeRow(selectedRow)
            }
        })
    }
}

frame.setVisible(true)

Menu System

import groovy.swing.SwingBuilder
import javax.swing.KeyStroke
import java.awt.event.KeyEvent

def swing = new SwingBuilder()

def frame = swing.frame(title: 'Menu Example', size: [500, 300]) {
    menuBar {
        menu(text: 'File', mnemonic: 'F') {
            menuItem(
                text: 'New',
                mnemonic: 'N',
                accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK),
                actionPerformed: { println 'New file' }
            )
            menuItem(
                text: 'Open',
                mnemonic: 'O', 
                accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK),
                actionPerformed: { println 'Open file' }
            )
            separator()
            menuItem(
                text: 'Exit',
                mnemonic: 'x',
                actionPerformed: { System.exit(0) }
            )
        }
        
        menu(text: 'Edit', mnemonic: 'E') {
            menuItem(text: 'Cut', accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK))
            menuItem(text: 'Copy', accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK))
            menuItem(text: 'Paste', accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK))
        }
        
        menu(text: 'View', mnemonic: 'V') {
            checkBoxMenuItem(text: 'Show Toolbar', selected: true)
            checkBoxMenuItem(text: 'Show Status Bar', selected: false)
            separator()
            
            // Radio button group
            def group = buttonGroup()
            radioButtonMenuItem(text: 'Small Icons', buttonGroup: group, selected: true)
            radioButtonMenuItem(text: 'Large Icons', buttonGroup: group)
        }
    }
    
    // Main content area
    textArea(text: 'Main content area...', editable: false)
}

frame.setVisible(true)

Data Binding

Automatic Data Binding

import groovy.swing.SwingBuilder
import groovy.beans.Bindable

class Person {
    @Bindable String firstName = ''
    @Bindable String lastName = ''
    @Bindable int age = 0
    @Bindable boolean employed = false
    
    String getFullName() {
        return "$firstName $lastName".trim()
    }
}

def swing = new SwingBuilder()
def person = new Person()

def frame = swing.frame(title: 'Data Binding Example', size: [400, 250]) {
    gridBagLayout()
    
    label(text: 'First Name:', constraints: gbc(gridx: 0, gridy: 0, anchor: WEST))
    textField(
        columns: 15,
        constraints: gbc(gridx: 1, gridy: 0, fill: HORIZONTAL),
        text: bind(source: person, sourceProperty: 'firstName', mutual: true)
    )
    
    label(text: 'Last Name:', constraints: gbc(gridx: 0, gridy: 1, anchor: WEST))
    textField(
        columns: 15,
        constraints: gbc(gridx: 1, gridy: 1, fill: HORIZONTAL),
        text: bind(source: person, sourceProperty: 'lastName', mutual: true)
    )
    
    label(text: 'Age:', constraints: gbc(gridx: 0, gridy: 2, anchor: WEST))
    spinner(
        model: spinnerNumberModel(minimum: 0, maximum: 120),
        constraints: gbc(gridx: 1, gridy: 2),
        value: bind(source: person, sourceProperty: 'age', mutual: true)
    )
    
    checkBox(
        text: 'Employed',
        constraints: gbc(gridx: 0, gridy: 3, gridwidth: 2),
        selected: bind(source: person, sourceProperty: 'employed', mutual: true)
    )
    
    separator(constraints: gbc(gridx: 0, gridy: 4, gridwidth: 2, fill: HORIZONTAL))
    
    label(
        text: bind(source: person, sourceProperty: 'fullName'),
        constraints: gbc(gridx: 0, gridy: 5, gridwidth: 2, anchor: CENTER),
        font: label().font.deriveFont(16f)
    )
    
    button(
        text: 'Print Info',
        constraints: gbc(gridx: 0, gridy: 6, gridwidth: 2),
        actionPerformed: {
            println "Person: ${person.fullName}, Age: ${person.age}, Employed: ${person.employed}"
        }
    )
}

frame.setVisible(true)

Custom Components

Custom Panel Component

import groovy.swing.SwingBuilder
import javax.swing.JPanel
import java.awt.Graphics
import java.awt.Color

class DrawingPanel extends JPanel {
    private List<Point> points = []
    
    DrawingPanel() {
        background = Color.WHITE
        addMouseListener([
            mouseClicked: { e ->
                points.add(new Point(e.x, e.y))
                repaint()
            }
        ] as java.awt.event.MouseAdapter)
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g)
        g.color = Color.BLUE
        points.each { point ->
            g.fillOval(point.x - 3, point.y - 3, 6, 6)
        }
    }
    
    void clearPoints() {
        points.clear()
        repaint()
    }
}

def swing = new SwingBuilder()

def drawingPanel = new DrawingPanel()

def frame = swing.frame(title: 'Custom Drawing Panel', size: [500, 400]) {
    borderLayout()
    
    widget(drawingPanel, constraints: BorderLayout.CENTER)
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout()
        button(text: 'Clear', actionPerformed: {
            drawingPanel.clearPoints()
        })
        button(text: 'Count Points', actionPerformed: {
            swing.optionPane().showMessageDialog(
                frame,
                "Points drawn: ${drawingPanel.points.size()}",
                'Point Count',
                swing.optionPane.INFORMATION_MESSAGE
            )
        })
    }
}

frame.setVisible(true)

Threading and EDT

Event Dispatch Thread Management

import groovy.swing.SwingBuilder
import javax.swing.SwingUtilities
import java.util.concurrent.Executors

def swing = new SwingBuilder()

def frame = swing.frame(title: 'Threading Example', size: [400, 200]) {
    borderLayout()
    
    def progressBar = progressBar(
        minimum: 0,
        maximum: 100,
        value: 0,
        stringPainted: true,
        constraints: BorderLayout.CENTER
    )
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout()
        
        button(text: 'Start Task', actionPerformed: {
            // Run long task in background thread
            swing.doOutside {
                (1..100).each { i ->
                    Thread.sleep(50)  // Simulate work
                    
                    // Update UI on EDT
                    swing.edt {
                        progressBar.value = i
                        progressBar.string = "Processing ${i}%"
                    }
                }
                
                // Final update on EDT
                swing.edt {
                    progressBar.string = "Complete!"
                    swing.optionPane().showMessageDialog(
                        frame,
                        'Task completed successfully!',
                        'Success',
                        swing.optionPane.INFORMATION_MESSAGE
                    )
                }
            }
        })
        
        button(text: 'Reset', actionPerformed: {
            progressBar.value = 0
            progressBar.string = null
        })
    }
}

frame.setVisible(true)

Timer-based Updates

import groovy.swing.SwingBuilder
import javax.swing.Timer
import java.text.SimpleDateFormat

def swing = new SwingBuilder()
def dateFormat = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss')

def frame = swing.frame(title: 'Clock Example', size: [300, 100]) {
    borderLayout()
    
    def timeLabel = label(
        text: dateFormat.format(new Date()),
        constraints: BorderLayout.CENTER,
        horizontalAlignment: swing.label.CENTER,
        font: label().font.deriveFont(18f)
    )
    
    // Update every second
    def timer = new Timer(1000) { e ->
        timeLabel.text = dateFormat.format(new Date())
    }
    timer.start()
    
    // Stop timer when window closes
    addWindowListener([
        windowClosing: { e -> timer.stop() }
    ] as java.awt.event.WindowAdapter)
}

frame.setVisible(true)

Styling and Look & Feel

Custom Look and Feel

import groovy.swing.SwingBuilder
import javax.swing.UIManager
import javax.swing.plaf.nimbus.NimbusLookAndFeel

// Set look and feel
try {
    UIManager.setLookAndFeel(new NimbusLookAndFeel())
} catch (Exception e) {
    println "Could not set Nimbus L&F: ${e.message}"
}

def swing = new SwingBuilder()

def frame = swing.frame(title: 'Styled Application', size: [400, 300]) {
    borderLayout()
    
    panel(constraints: BorderLayout.NORTH, background: java.awt.Color.LIGHT_GRAY) {
        flowLayout()
        label(text: 'Styled Header', font: label().font.deriveFont(16f))
    }
    
    tabbedPane(constraints: BorderLayout.CENTER) {
        panel(name: 'Tab 1') {
            gridLayout(rows: 3, cols: 2, hgap: 10, vgap: 10)
            label(text: 'Name:')
            textField(columns: 15)
            label(text: 'Email:')
            textField(columns: 15)
            label(text: 'Notes:')
            scrollPane {
                textArea(rows: 3, columns: 15)
            }
        }
        
        panel(name: 'Tab 2') {
            boxLayout(axis: swing.boxLayout.Y_AXIS)
            checkBox(text: 'Option 1')
            checkBox(text: 'Option 2')
            checkBox(text: 'Option 3')
            separator()
            radioButton(text: 'Choice A')
            radioButton(text: 'Choice B')
        }
    }
    
    panel(constraints: BorderLayout.SOUTH) {
        flowLayout()
        button(text: 'OK', preferredSize: [80, 30])
        button(text: 'Cancel', preferredSize: [80, 30])
        button(text: 'Apply', preferredSize: [80, 30])
    }
}

frame.setVisible(true)

This comprehensive documentation covers all the major aspects of Groovy's Swing integration, from basic components to advanced features like data binding, custom components, and threading. The SwingBuilder provides a powerful and expressive way to create desktop applications with minimal boilerplate code.

Install with Tessl CLI

npx tessl i tessl/maven-org-codehaus-groovy--groovy-all

docs

ast-transforms.md

cli.md

core-language.md

index.md

json.md

sql.md

swing.md

templates.md

xml.md

tile.json