I want to create a fully transparent background for a Frame (or JFrame) and have it show a transparent animation. I managed to get it working in Windows 7 x64 but the same code does not run on my Linux (Lubuntu x64 15.04).
The code below shows what I'm trying to achieve--just copy & paste it. I just want the little rectangle to move across the screen without leaving a trail.
static int  a   = 0;
public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setUndecorated(true);
    f.setBackground(new Color(0, 0, 0, 0));
    f.setVisible(true);
    f.setSize(512, 512);
    f.add(new JPanel() {
        @Override
        public void paintComponent(Graphics gr) {
            Graphics2D g = (Graphics2D)gr;
            g.setBackground(new Color(0, 0, 0, 0));
            g.clearRect(0, 0, 512, 512);
            g.drawRect(a, a++, 2, 2);
        }
    });
    while(true) {
        try {
            Thread.sleep(30);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        f.repaint();
    }
}
What I want to achieve (as shown in Windows) and what I get with Lubuntu 15.04:
         

I just want to see the little square move just like what's shown on Windows 7--I don't want to see a trail.
Please don't give me the link of Oracle's transparency and window documentation--I've gone over it all thrice.
What I've tried:
Please please just test out your thoughts/code first. A lot of the "this should work" stuff I have already tried and does not seem to... All help is greatly appreciated.
For reference, here's a minimal complete example, suitable for cross-platform testing. Note that
On some platforms, e.g. Ubuntu, a completely transparent background is not seen as opaque; a small, non-zero alpha value is a typical work-around.
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
Use java.swing.Timer, which runs on the event dispatch thread, to pace the animation.
Don't use setPreferredSize() when you really mean to override getPreferredSize().

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
 * @see https://stackoverflow.com/a/31328464/230513
 */
public class TransparentAnimation {
    private static final Color tranparentBlack = new Color(0, 0, 0, 1);
    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setUndecorated(true);
        f.setBackground(tranparentBlack);
        f.add(new JPanel() {
            int x, y;
            Timer t = new Timer(10, (ActionEvent e) -> {
                x = (x + 1) % getWidth();
                y = (y + 1) % getHeight();
                repaint();
            });
            {
                setBackground(tranparentBlack);
                t.start();
            }
            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
                g.fillOval(x, y, 16, 16);
            }
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(320, 240);
            }
        });
        f.add(new JLabel(System.getProperty("os.name") + "; v"
            + System.getProperty("os.version")), BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new TransparentAnimation()::display);
    }
}
                        Basically this issue is OS-related. What works for Windows will not work for Linux and vice versa.
For some reason, Linux only allows animated per-pixel-transparency when setting up a BufferStrategy. However, this solution fails on Windows. As a result I have come up with the following code which picks the correct algorithm based on the OS:
static int a = 0;
public static void main(String[] args) {
    JFrame f = new JFrame();
    JPanel p = new JPanel() {
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setBackground(new Color(255, 255, 255, 0));
            g2d.clearRect(0, 0, f.getWidth(), f.getHeight());
            g2d.drawRect(a, a++, 2, 2);
        }
    };
    f.add(p);
    f.setUndecorated(true);
    f.setBackground(new Color(255, 255, 255, 0));
    f.setSize(512, 512);
    f.setVisible(true);
    f.createBufferStrategy(2);
    BufferStrategy bs = f.getBufferStrategy();
    while (true) {
        try {
            Thread.sleep(33);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (System.getProperty("os.name").contains("indows ")) {
            p.repaint();
        } else {
            Graphics g = null;
            do {
                try {
                    g = bs.getDrawGraphics();
                    p.update(g);
                } finally {
                    g.dispose();
                }
                bs.show();
            } while (bs.contentsLost());
            Toolkit.getDefaultToolkit().sync();
        }
    }
}
This code works for my Windows 7 x64 and my Lubuntu 15.04 x64. Please try out this code out yourself and see if it works for you. I myself don't own a Mac so if someone would please test it for me I would be very grateful. If it does not work for anyone, please let me know.
This is what you're supposed to see:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With