The frame background can have transparency, at least for the JAVA2D / “default” renderer in Processing. Here’s a post the question of which shows code for doing so:
I had myself used this technique many months ago, and it works nicely! I don’t know if the code in the aforementioned post still works as expected, but feel free to ask me for my old code if it doesn’t.
Hello there…
…Iiiiiiiii know it has been 6 months, but it’s important that I write the answer here even though I’m this terribly late. At least for future readers.
…
Steps on how I did that back then:
Use the JAVA2D renderer in your call to size(),
Now we write some Java AWT code!
Get the AWT JFrame from your Processing sketch by using PApplet::getSurface(), then calling PSurface::getNative() on it, and casting it to a JFrame.
Give it a transparent background using JFrame::setBackground(). Pass a new Color(0, 0, 0, 1) into it. I think this has to be repeated in PApplet::draw().
Call JFrame::setOpacity() with 0.5f or a similar value. Setting the alpha in the background-color to 1 in the [1, 255] range that AWT accepts is enough only on Windows; opacity control is required everywhere else. It’s just neater to use it anyway…!
I also realized that I essentially re-created Processing’s event-handling using AWT listeners, but in a poorer manner - one that does not consider using PApplet::handle*Event() methods. That part is apparently entirely useless!
All we’re doing here is literally “[busy-]waiting” until the GLWindowis fullscreen. Tracking time.
…Like every other time, here’s a simpler Processing sketch that should get you started [and done!]:
NullPointerException
java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because "this.removals" is null
at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1333)
at processing.core.PApplet.handleMethods(PApplet.java:1460)
at processing.core.PApplet.handleDraw(PApplet.java:2127)
at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:840)
at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:797)
at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:471)
at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:245)
at java.base/java.util.TimerThread.mainLoop(Timer.java:566)
at java.base/java.util.TimerThread.run(Timer.java:516)
NullPointerException
TL;DR: Debian 12 or 13 (with KDE Plasma, atop X11), Windows 11 or 10. Processing 3.5.4!
I initially wanted to mention I myself was on Debian [13, with KDE Plasma and sddm, atop X11 (also 12…!)], but I recalled that JFrame::setOpacity() and even the GLWindow methods work on Windows [10 and 11], too!
(I have tested on all OSs mentioned here.)
…So while I don’t immediately changing between Windows or Linux matters, the version of Processing absolutely does! And I’m sorry to all those I disappoint: All of my code works with Processing 3.5.4. I’m sorry I did not consider Processing 4…!
I’m somewhat confident most of these “hacks” can be “translated” over. Though… I’m not aware of Processing 4’s internal changes. Will have to look into those.
Regardless, I hope we can do that!
Unfortunately, much of my work isn’t with Processing these days, so I can’t say how long it’ll take me to figure this out, but I’ll try :)!
PS I apologize in advance that my responses are going to be a few hours late.
/*
* This Processing sketch was generated with the help of ChatGPT.
* Date: 2026-01-23
*/
import java.awt.Frame; // Java's standard window class (AWT = Abstract Window Toolkit)
import processing.awt.PSurfaceAWT; // Processing class that bridges its sketch to a Java AWT window
Frame frame; // This will hold the actual window (AWT Frame) that contains the Processing canvas
void settings() {
// Create a 400x200 JAVA2D sketch
// JAVA2D is Processing's default 2D renderer that draws using Java2D graphics
size(400, 200, JAVA2D);
}
void setup() {
// ---------------------------
// Understanding the "surface"
// ---------------------------
// In Processing, the 'surface' is the object that represents where your sketch draws.
// It manages the connection between Processing's drawing commands and the actual window.
// For JAVA2D sketches, the surface wraps an AWT Frame and a Canvas inside it.
PSurfaceAWT awtSurface = (PSurfaceAWT) surface; // Cast Processing's surface to an AWT-specific version
// Get the canvas inside the surface
// The canvas is the actual drawing area inside the window (where background(), text(), etc. appear)
PSurfaceAWT.SmoothCanvas canvas = (PSurfaceAWT.SmoothCanvas) awtSurface.getNative();
// ---------------------------
// Understanding the AWT Frame
// ---------------------------
// An AWT Frame is Java's object for a window with borders, title bar, and close/minimize buttons.
// The "native peer" refers to the actual OS-level window that the Frame represents.
// Processing creates this automatically when you call size().
frame = (Frame) canvas.getFrame();
// ---------------------------
// Make the window borderless
// ---------------------------
// To remove the OS window decorations safely, we must first dispose the native peer
frame.dispose(); // Temporarily destroys the OS window
frame.setUndecorated(true); // Remove title bar and borders
frame.setResizable(false); // Optional: disable resizing
frame.setVisible(true); // Show the frame again (now borderless)
// Ensure Processing knows the canvas size, syncing it with the frame
surface.setSize(width, height);
// ---------------------------
// Text setup
// ---------------------------
textAlign(CENTER, CENTER); // Center text horizontally and vertically
textSize(24); // Text size
fill(255); // White text
}
void draw() {
background(255, 0, 0); // Solid red background
text("Borderless JAVA2D Window", width / 2, height / 2);
}
// ---------------------------
// Optional: ESC key handling
// ---------------------------
// Pressing ESC will close the sketch cleanly.
// Processing automatically calls exit() on ESC, so this is optional.
void keyPressed() {
if (key == ESC) {
key = 0; // Prevent default Processing ESC behavior
println("So long folks!");
delay(1000);
exit(); // Close the sketch cleanly
}
}
ChatGPT was used because this is an advanced topic and was able to generate a working and commented example. It took several passes and was a useful tool for an experienced user. The response should be subjected to scrutiny.