How To Stop Jframe From Flashing When Resizing
enersection
Mar 18, 2026 · 10 min read
Table of Contents
When you resize a Swing JFrame, you may notice a brief flash or flicker as the window’s contents are redrawn. This visual artifact is distracting, especially in applications that require smooth user interaction such as drawing tools, games, or data‑visualization panels. The flicker originates from the way the AWT event‑dispatch thread handles paint requests during a resize operation: the window is cleared, repainted, and then the new size is applied, causing a momentary blank or partially drawn frame. Fortunately, the Java Swing toolkit provides several mechanisms to eliminate or greatly reduce this flashing. Below is a comprehensive guide that explains why the flash occurs and walks you through practical steps to stop it.
Understanding the Flashing Issue
Before diving into solutions, it helps to know what triggers the flicker:
- Paint‑buffer clearing – When the JFrame receives a
ComponentResizedevent, Swing may clear the off‑screen buffer before issuing a repaint. - Synchronous repaint requests – The default repaint manager can coalesce multiple paint requests, but during a rapid resize stream it sometimes issues immediate paints that bypass double buffering.
- Look‑and‑feel decorations – Some LAFs draw borders or title bars in a separate pass, which can appear as a flash if the client area is repainted at a different time.
- Heavyweight components – Mixing AWT heavyweight controls (e.g.,
Canvas,Panel) with Swing lightweight components can cause mismatched paint cycles.
The core idea behind most fixes is to ensure that the window’s content is always drawn to an off‑screen image before being blitted to the screen, and to prevent the window manager from clearing the background between frames.
Step‑by‑Step Guide to Stop JFrame Flashing
1. Enable Double Buffering for the JFrame’s Content Pane
Swing components are double‑buffered by default, but the top‑level window itself is not. You can force double buffering on the root pane by setting the BufferedImage strategy or by using the RepaintManager.
import java.awt.*;
public class FlickerFreeFrame extends JFrame {
public FlickerFreeFrame() {
setTitle("Flicker‑Free JFrame");
setSize(800, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// Enable double buffering for the root pane
RepaintManager currentManager = RepaintManager.currentManager(this);
currentManager.setDoubleBufferingEnabled(true);
// Optional: make the content pane opaque to avoid background clearing
getContentPane().setOpaque(true);
add(new DrawingPanel()); // your custom component
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FlickerFreeFrame().setVisible(true));
}
}
Why it works: The RepaintManager now buffers all paint requests for the window’s hierarchy in an off‑screen image, copying the final result to the screen in a single blit. This removes the intermediate clear‑paint cycle that causes the flash.
2. Set the JFrame’s IgnoreRepaint Flag to False (Default) and Use Proper Paint Methods
Avoid overriding paint(Graphics g) on the JFrame itself. Instead, perform custom drawing in a lightweight component (e.g., JPanel, JComponent) and override its paintComponent(Graphics g) method. The JFrame’s default paint delegate simply forwards to the content pane, preserving double buffering.
class DrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // clears background using double buffer
// Your custom drawing code here
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// example: draw a moving rectangle
int x = (getWidth() - 50) / 2;
int y = (getHeight() - 50) / 2;
g2.setColor(Color.BLUE);
g2.fillRect(x, y, 50, 50);
}
}
Why it works: paintComponent is invoked only after the double‑buffered image is ready, and calling super.paintComponent(g) ensures the background is cleared correctly without exposing an intermediate blank state.
3. Use setIgnoreRepaint(false) on the JFrame (explicitly)
Although the default is false, some look‑and‑feels or third‑party libraries may toggle this flag inadvertently. Reinforce the desired state after constructing the frame:
setIgnoreRepaint(false);
Why it works: When ignoreRepaint is true, Swing discards paint requests, forcing the toolkit to rely on the native window system’s painting, which often skips double buffering and leads to flicker.
4. Apply a Constant Background Color or Image
If the JFrame’s content pane is translucent or has a varying background, each resize may cause the window manager to repaint the underlying desktop briefly. Setting a solid, opaque background eliminates this source of flash:
getContentPane().setBackground(Color.WHITE);
getContentPane().setOpaque(true);
Why it works: An opaque background guarantees that every pixel is covered during each paint pass, preventing the windowing system from showing the desktop or parent container between frames.
5. Disable Window Decorations During Rapid Resizes (Advanced)
In some cases, the title bar and borders are repainted separately from the client area, causing a perceptible lag. You can temporarily remove decorations while the user is dragging the border, then restore them after the resize ends. This technique requires listening to the ComponentListener and using setUndecorated(true)—note that this makes the frame undecorated, so you must re‑add your own title bar if needed.
addComponentListener(new ComponentAdapter() {
private boolean wasDecorated = true;
@Override
public void componentResized(ComponentEvent e) {
if (wasDecorated) {
// Remove decorations while resizing
setUndecorated(true);
wasDecorated = false;
}
}
@Override
public void componentMoved(ComponentEvent e) {
// Restore decorations after the user stops moving/resizing if (!wasDecorated) {
setUndecorated(false);
wasDecorated = true;
}
}
});
Why it works: By eliminating the decorative layer during the resize, you reduce the number of paint passes. The trade‑off is loss of native window chrome; you must replace it with custom UI if you need buttons for minimize/maximize/close.
6. Use BufferStrategy for Canvas‑Based Rendering (If You Need Heavy‑Weight Drawing)
If your application relies on a Canvas or BufferStrategy (common in game loops), ensure you are using page flipping correctly:
canvas.createBufferStrategy(2); // double buffering
BufferStrategy bs = canvas.getBufferStrategy();
while (running) {
do {
Graphics g
### Conclusion
The flicker experienced during window resizing in Java Swing is primarily a byproduct of the windowing system’s painting pipeline, which may expose intermediate states or skip double buffering under certain conditions. The techniques outlined above tackle this issue from multiple angles:
1. **Double Buffering (`setIgnoreRepaint(false)`)** ensures that Swing’s rendering is synchronized with the display, minimizing intermediate visual artifacts.
2. **Opaque Backgrounds** eliminate transparency-related flicker by guaranteeing full coverage during repaints.
3. **Temporary Decoration Removal** reduces the complexity of repaints during resizing, though it requires manual UI management.
4. **Canvas-Level Rendering** offers granular control over the painting process, ideal for performance-critical applications like games or animations.
While no single method is universally optimal, combining these strategies—such as pairing `setIgnoreRepaint(false)` with an opaque background—often provides the smoothest user experience. Developers should experiment with these approaches based on their application’s requirements, balancing performance, visual fidelity, and complexity. By understanding the underlying causes of flicker and applying targeted solutions, Java Swing applications can achieve polished, responsive resizing behavior.
### 6. Using`BufferStrategy` for Canvas‑Based Rendering (If You Need Heavy‑Weight Drawing)
When a `Canvas` (or any lightweight component) becomes the primary drawing surface, the default Swing repaint cycle can introduce an extra repaint pass that sometimes manifests as flicker during resize. Switching to an explicit `BufferStrategy` gives you full control over when the graphics are flushed to the screen.
```java
import java.awt.*;
import javax.swing.*;
public class ResizableCanvasDemo extends JFrame {
private final Canvas canvas = new Canvas();
public ResizableCanvasDemo() {
super("Canvas with BufferStrategy");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// Add the canvas to the frame
add(canvas, BorderLayout.CENTER);
setSize(600, 400);
setLocationRelativeTo(null);
// Enable double buffering with a 2‑buffer strategy
canvas.createBufferStrategy(2);
BufferStrategy bs = canvas.getBufferStrategy();
// Register a listener that forces a repaint only when the window is idle
addComponentListener(new java.awt.event.ComponentAdapter() {
@Override
public void componentResized(java.awt.event.ComponentEvent e) {
// Ensure the strategy matches the new size
if (bs != null && !bs.isCompatible()) {
canvas.createBufferStrategy(2);
bs = canvas.getBufferStrategy();
}
// Trigger a repaint but let the buffering handle the actual drawing
canvas.requestFocus();
canvas.repaint();
}
});
// Main rendering loop
new Thread(() -> {
while (true) {
// 1️⃣ Acquire the next drawing surface
Graphics2D g = null;
try {
g = (Graphics2D) bs.getDrawGraphics();
// 2️⃣ Clear the buffer
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
// 3️⃣ Draw your scene – example rotating square
drawScene(g);
// 4️⃣ Show the rendered frame
g.dispose();
bs.show();
} finally {
if (g != null) g.dispose();
}
// 5️⃣ Sleep a short while to keep CPU usage reasonable
try {
Thread.sleep(16); // ~60 fps
} catch (InterruptedException ignored) {}
}
}).start();
}
/** Simple demo drawing routine */
private void drawScene(Graphics2D g) {
int w = getWidth();
int h = getHeight();
// Compute a rotating angle based on time
double angle = System.currentTimeMillis() / 1000.0 * Math.PI / 4;
double cx = w / 2.0;
double cy = h / 2.0;
int size = Math.min(w, h) / 4;
g.setColor(Color.CYAN);
g.translate(cx, cy);
g.rotate(angle);
g.fillRect(-size, -size, size * 2, size * 2);
g.rotate(-angle);
g.translate(-cx, -cy);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new ResizableCanvasDemo().setVisible(true));
}
}
Key take‑aways from the snippet
- Explicit strategy creation – By calling
createBufferStrategy(2)(or3for triple buffering) you decide how many off‑screen buffers exist. A larger strategy reduces the chance that the system will fall back to a single‑buffer mode that can cause flicker. - Compatibility check – Whenever the component is resized the buffer must be recreated; otherwise
show()will throw anIllegalStateException. - Separate rendering thread – Running the drawing loop in its own thread decouples the UI event dispatch from the animation frames, preventing the EDT from being blocked and guaranteeing that each frame is rendered on a clean buffer.
- Full‑screen clearing – Filling the entire buffer with a solid background eliminates any leftover pixels from the previous frame, which is the most common source of visual “ghosting” during resize.
- Dispose of
Graphics2D– Always calldispose()after you finish drawing to return the resources to the pool and avoid subtle rendering glitches.
If your application already uses a JPanel for UI controls and a separate Canvas for the heavy‑weight scene, keep the two hierarchies isolated. The panel can stay fully decorated, while the canvas handles
Optimizing Animation Performance inSwing Applications
The core challenge in Swing animation lies in synchronizing smooth visual updates with the Event Dispatch Thread (EDT). While the provided code demonstrates a functional rotating square, deeper optimization and best practices can elevate its performance and stability. The explicit creation of a double buffer strategy (createBufferStrategy(2)) is foundational. This prevents the system from defaulting to single-buffering, which causes visible flicker during rapid updates. However, the strategy's size (2 buffers) is a critical parameter. For complex scenes or high frame rates, consider increasing this value to 3 or 4, reducing the likelihood of buffer exhaustion and ensuring seamless frame swapping. Always validate the strategy's existence before rendering (if (bs != null)) to gracefully handle resize scenarios where the buffer may need recreation.
Running the rendering loop in a dedicated thread is non-negotiable. It isolates the computationally intensive animation logic from the EDT, preventing UI responsiveness degradation. This separation allows the animation to maintain a consistent frame rate (Thread.sleep(16) approximates 60 FPS) even during heavy processing elsewhere in the application. Crucially, the loop must be designed to terminate cleanly on application exit, avoiding resource leaks. The finally block ensures the Graphics2D context is always disposed, freeing underlying resources and preventing subtle rendering artifacts. This disciplined resource management is often overlooked but vital for long-running applications.
Resizing introduces unique challenges. The componentResized method explicitly recreates the buffer strategy, a necessary safeguard. However, the full-screen clear (g.fillRect(0, 0, getWidth(), getHeight())) is equally important. It eliminates residual pixels from the previous frame, which is the primary cause of "ghosting" during resizing. This step, combined with the buffer strategy recreation, ensures the new frame starts with a pristine canvas. The animation loop itself must be resilient to these resize events, seamlessly transitioning to the new buffer without visual glitches.
Conclusion
Mastering Swing animation requires a holistic approach: strategic buffer management, thread separation, robust resource handling, and proactive handling of component state changes like resizing. The rotating square example illustrates these principles effectively, but its success hinges on understanding the underlying mechanisms. By explicitly controlling the buffer strategy, isolating rendering from the EDT, rigorously managing resources, and ensuring a clean slate for each frame (especially during resize), developers can achieve smooth, flicker-free animations even in complex Swing applications. These practices are not merely optimizations; they are fundamental requirements for professional-grade UI responsiveness and visual fidelity in Java Swing.
Latest Posts
Latest Posts
-
How To Add Matrices In Mathematica
Mar 18, 2026
-
Is Blue Eyes A Recessive Trait
Mar 18, 2026
-
Truss Analysis By Method Of Sections
Mar 18, 2026
-
Is Evaporating Water A Chemical Change
Mar 18, 2026
-
Therefore The Sum Of Two Rational Numbers Will Always Be
Mar 18, 2026
Related Post
Thank you for visiting our website which covers about How To Stop Jframe From Flashing When Resizing . We hope the information provided has been useful to you. Feel free to contact us if you have any questions or need further assistance. See you next time and don't miss to bookmark.