UI Visualisation
Real-time Swing rendering of cellular automata using CellularAutomataUIRunner.
Overview
The io.github.carmelolg.jcal.ui package provides a Swing-based visualisation layer
that renders the evolution of a cellular automaton in real time.
The fastest way to get a window on screen is the CellularAutomataUIRunner fluent façade.
For more control (custom layouts, multiple windows, manual threading) you can wire the
lower-level components — CellularAutomataDisplay and AutomataListener — directly.
Quick Start: CellularAutomataUIRunner
CellState DEAD = new CellState("dead", "0");
CellState ALIVE = new CellState("alive", "1");
CellularAutomata ca = new CellularAutomata(config);
CellularAutomataUIRunner.create(ca, new GameOfLifeRule())
.title("Game of Life — JCAL")
.cellSize(14)
.delay(80) // ms between frames
.renderer(state -> state.equals(ALIVE) ? Color.GREEN : Color.BLACK)
.start();
start() opens the window and launches the automaton on a background daemon thread,
keeping the Swing EDT free. The method returns immediately.
Builder options
| Method | Default | Description |
|---|---|---|
.title(String) |
"JCAL Automata" |
Window title |
.cellSize(int) |
10 |
Pixel size of each cell |
.delay(int) |
100 |
Milliseconds between generations (0 = no delay) |
.renderer(CellRenderer) |
(required) | Maps a CellState to a java.awt.Color |
start() without a renderer throws IllegalStateException.Components
CellRenderer
A @FunctionalInterface that maps a cell’s CellState to a java.awt.Color.
CellRenderer renderer = state -> state.equals(ALIVE) ? Color.GREEN : Color.BLACK;
Implement more complex renderers with a lambda or anonymous class:
CellRenderer heatRenderer = state -> {
int temp = (int) state.getValue();
return new Color(Math.min(255, temp * 2), 0, Math.max(0, 255 - temp * 2));
};
AutomataListener
AutomataListener implements GenerationListener and forwards each snapshot to a
GridDisplay. It optionally introduces a delay to throttle the animation.
AutomataListener listener = new AutomataListener(display, 100); // 100 ms per frame
rule.addGenerationListener(listener);
The delay is applied on the execution thread, so the Swing EDT remains unblocked.
CellularAutomataDisplay
A JFrame-backed window that owns a GridPanel (for rendering) and a status label
showing the current generation number.
CellularAutomataDisplay display = new CellularAutomataDisplay("Game of Life", renderer, 14);
display.show();
AutomataListener listener = new AutomataListener(display, 80);
rule.addGenerationListener(listener);
// Run on a background thread
new Thread(() -> {
try { rule.run(ca); } catch (Exception e) { e.printStackTrace(); }
}, "jcal-runner").start();
All Swing mutations inside CellularAutomataDisplay are dispatched on the EDT via
SwingUtilities.invokeLater.
GridDisplay
An interface that any display component can implement to be driven by an AutomataListener:
public interface GridDisplay {
void update(GridSnapshot snapshot);
}
You can provide a custom GridDisplay (e.g., a JavaFX wrapper or a test stub) to
AutomataListener instead of CellularAutomataDisplay.
Full Manual Example
CellularAutomataDisplay display = new CellularAutomataDisplay(
"My Automaton", heatRenderer, 10);
display.show();
CellularAutomataRule rule = new HeatDiffusionRule();
rule.addGenerationListener(new AutomataListener(display, 50));
Thread runner = new Thread(() -> {
try {
rule.run(ca);
display.close(); // close the window when evolution ends
} catch (Exception e) {
e.printStackTrace();
}
}, "jcal-runner");
runner.setDaemon(true);
runner.start();
Running UI Examples
The project ships three ready-to-run UI examples:
# Game of Life — glider + blinker on a 40×40 grid
mvn compile exec:java \
-Dexec.mainClass="io.github.carmelolg.jcal.examples.GameOfLifeUiExample"
# 3D Carter Bays' Life with Swing visualisation
mvn compile exec:java \
-Dexec.mainClass="io.github.carmelolg.jcal.examples.GameOfLife3DUiExample"
# Advanced patterns
mvn compile exec:java \
-Dexec.mainClass="io.github.carmelolg.jcal.examples.GameOfLifeAdvancedUiExample"
See Game of Life UI Example for the full annotated source.
See Also
- Generation Listeners — the
GenerationListener/GridSnapshotAPI. - Implementing a Rule — writing the transition function.