3

I'm trying to make an anti-aliased shaped window (circle) in the same fashion as this answer, but that one suffers from the same issue: when repainting, as soon as paintComponent is called, the window disappears, to re-appear after the call returns.

I don't know if this has to do with my particular machine, or the fact that I run Ubuntu instead of Windows, in Xorg instead of Wayland or OpenJDK instead of Oracle. On another computer where all these items are different from my work PC, this issue doesn't occur.

Transparent window which flickers on repaint

Minimum example:

import java.awt.*;
import java.util.concurrent.*;
import javax.swing.*;

public class AntialiasedWindow extends JPanel {
    public static void main(String... args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setUndecorated(true);
            f.setBackground(new Color(0, 0, 0, 0));
            f.setContentPane(new AntialiasedWindow());
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }

    public AntialiasedWindow() {
        super(null);
        setOpaque(false);
        setPreferredSize(new Dimension(256, 256));

        new Timer(250, e->repaint()).start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        ((Graphics2D)g).setRenderingHints(new RenderingHints(
                RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

        g.setColor(Color.DARK_GRAY);
        g.clearRect(0, 0, getWidth(), getHeight());
        g.fillArc(0, 0, getWidth(), getHeight(), 85, 270);

        //try { Thread.sleep(100); } catch (InterruptedException ignored) { }  // Flickering gets worse with this
    }
}

What I tried:

  • JWindow instead of JFrame
  • JComponent instead of JPanel
  • Non-transparent JPanel (flicker stops but transparent pixels accumulate until near opaque)
  • Single/double buffering
  • With/without alwaysOnTop
  • With default, System and Nimbus LAFs
  • With Bufferstrategy instead of paintComponent: The frame stops being transparent, but I probably don't know what I'm doing.
Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
  • 1
    Why do you have a `Thread.sleep` inside your paint method? – khelwood May 01 '20 at 15:43
  • 1
    Read the comment. Flickering gets worse when the paint method is busy. In reality I do some simple gepmetry drawing which takes a small amount of time (although admittedly not nearly as long, but still visible). – Mark Jeronimus May 01 '20 at 16:10
  • Do your long-running code in a background thread, ***never*** on the event thread, and ***absolutely never*** directly slow down graphics rendering as you're doing. – Hovercraft Full Of Eels May 01 '20 at 16:12
  • That's what I'm doing. I know that. The delay is just for the sake of the issue. Just remove the delay and see: just clearing and drawing an arc (or oval for that matter) makes the window flicker for 1/60s (on a 60Hz screen) – Mark Jeronimus May 01 '20 at 16:16
  • For repeated swig gui updates use [swing timer](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) : `new Timer(250, e->repaint()).start();` – c0der May 01 '20 at 16:43
  • Ok, but the issue doesn't change. Could anyone reproduced this on his/her box? – Mark Jeronimus May 01 '20 at 17:00

0 Answers0