Configuring Processing Sketch Surfaces in settings() Instead of setup()
Since Processing 3.0, surface configuration must happen in settings() before the window exists. This guide shows how to migrate legacy sketches, choose renderers, and handle HiDPI pixel density.
05 Jan 2026, 10:15 UTC

If you open a Processing 2.x sketch in Processing 3 or 4 and the window never appears, or the PDE console reports an error about size() and settings(), the cause is almost always the same: the sketch is still calling size() from setup(). Since Processing 3.0, the runtime invokes a separate settings() method exactly once, before the sketch window and drawing surface exist. Surface configuration—window dimensions, renderer choice, and pixel density—must happen there. Keeping those calls in setup() is either ignored or throws because the surface is already created.
The practical rule is simple: use settings() for surface configuration, and use setup() for state initialization and asset loading. This guide walks through that split, shows how to verify it on your installed version, and covers recovery options for legacy code.
Desired Outcome
A sketch that configures its drawing surface exactly once in settings(), initializes variables and loads assets in setup(), and produces predictable coordinates and output regardless of display density. The same code should behave consistently in the PDE, on HiDPI hardware, and after export.
Prerequisites
- Processing 3.0 or later. The
settings()lifecycle does not exist in 1.x or 2.x. If you are on Processing 4, note that internal window and surface handling changed compared with 3.x, so verify surface-related behavior on your specific build. - A basic understanding that the Processing Development Environment (PDE) calls
settings(),setup(), anddraw()in that order. You do not callsettings()yourself. - For renderer experiments, awareness that
FX2Davailability depends on the distribution and Java version. Confirm it exists before committing a sketch to it.
Focused Procedure
1. Move surface calls into settings()
Create a settings() method and move every surface-defining call into it. These include size(w, h, renderer), fullScreen(), fullScreen(renderer), pixelDensity(n), and smooth(). The third argument to size() selects the renderer—the graphics backend Processing uses to draw: JAVA2D for standard 2D, P2D for hardware-accelerated 2D, P3D for 3D, and FX2D for a JavaFX-based pipeline.
void settings() {
size(800, 600, P2D);
pixelDensity(displayDensity());
smooth(4);
}
Leave setup() for everything else: variable initialization, loadImage(), loadFont(), reading data files, and configuring drawing state that does not define the surface itself.
2. Keep setup() for state and assets
A common mistake is calling size() from draw() or from event handlers such as mousePressed(). Do not do this. The surface is created once. If you need to change the window size later, use the surface API rather than size(), and verify the exact method name for your Processing version because 4.x changed surface handling.
3. Handle pixel density explicitly on HiDPI displays
On Retina and other HiDPI (high-density) displays, pixelDensity() is clamped to displayDensity(). If you request a density the display does not support, the runtime silently uses the closest supported value. The variables width and height remain in sketch coordinate units even when the backing store—the actual pixel buffer—is larger, but raw pixels[] indexing must use width * pixelDensity() as the row stride. To avoid this complexity, use get() and set() instead of direct array access.
If you want mouse coordinates and drawing units to stay in predictable 1:1 values, call pixelDensity(1) after fullScreen(). This is a common pattern for sketches where coordinate math matters more than display sharpness.
4. Make output reproducible
For deterministic artifacts, combine a fixed surface setup with noLoop() and explicit redraw(), or drive animation with a frame counter. Emit results using saveFrame() or beginRecord() rather than relying on draw() timing.
Expected Checks
Diagnostic sketch
Write a minimal sketch that prints the renderer name, width, height, pixelDensity(), and displayDensity() from both settings() and setup(). Run it in the PDE. The settings() output should appear before the window is visible; the setup() output should appear after. Compare the values against the reference documentation for your installed version.
Legacy migration check
Open a legacy Processing 2.x sketch that calls size() in setup(). Confirm that the PDE console reports the expected settings()/size() error before you migrate it. After moving the call into settings(), the error should disappear and the window should appear at the requested dimensions.
HiDPI coordinate check
Run the same sketch on a HiDPI display with default pixel density, then again with pixelDensity(1). Check that mouseX and mouseY map to drawing coordinates as expected. If mouseX seems offset or scaled, the density likely did not take effect as requested.
Exported application check
Use Export Application and launch the result outside the PDE. Confirm that window size, renderer, and asset loading behave identically to the editor preview. Remember that exported applications resolve the data folder differently from the editor; use sketchPath() or dataPath() rather than hard-coded relative paths.
Recovery Options
| Symptom | Likely cause | Recovery |
|---|---|---|
Window does not appear; console mentions settings() and size() | size() called from setup() in a Processing 3+ sketch | Move size() into settings() and reload the sketch |
pixelDensity() seems ignored | Requested density clamped to displayDensity() | Print pixelDensity() and displayDensity(); accept the clamped value or force pixelDensity(1) |
Sketch uses FX2D but fails to start | FX2D unavailable in this distribution or Java version | Switch to JAVA2D, P2D, or P3D and retest |
| Assets load in PDE but not in exported app | Data folder path resolved differently at runtime | Use dataPath() or sketchPath() to locate files |
Limitations and Version Notes
Processing 4 changed internal window and surface handling compared with 3.x. Behavior of surface.setResizable(), multiple windows, and full-screen spans can differ between versions. If a sketch depends on those features, test on the exact version you intend to distribute.
pixelDensity() clamping is silent. Do not assume the requested value took effect without printing the actual density. Similarly, FX2D is not guaranteed across all Processing distributions or Java versions.
Finally, the split between settings() and setup() is not merely stylistic. The runtime creates the drawing surface after settings() returns and before setup() begins. Any attempt to redefine the surface from setup(), draw(), or an event handler fights the lifecycle rather than working with it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.