1

When painting over a transparent window, the window is not correctly repainted and previously drawn objects still show off. See this example (Ubuntu 14.04, 1.8.0_141).

Case 1 : We paint the image from a transparent JPanel over a transparent JFrame. Case 2 : We paint the image directly over the JFrame.

package test;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TranscluentWindow extends JFrame {
    /** The image we will draw on the frame **/
    private final BufferedImage test = generateImage();
    /** The location where to paint the image **/
    private Point p = new Point();
    /** Set up the GUI **/
    public TranscluentWindow() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setUndecorated(true);
        setExtendedState(MAXIMIZED_BOTH);
        setBackground(new Color(0, 0, 0, 0));
        //Disable this line for case 2
        setContentPane(new TranslucentPane());
        getContentPane().addMouseMotionListener(new MouseDragListener());
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TranscluentWindow().setVisible(true);
            }
        });
    }

    /** Move the image on the frame **/
    private class MouseDragListener extends MouseAdapter {
        @Override
        public void mouseMoved(MouseEvent e) {
            p = e.getPoint();
            repaint();
        }
    }

    /** Capture an image of any component **/
    private static BufferedImage getImage(Component c) {
        if(c==null) return null;
        BufferedImage image = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        c.paint(g);
        return image;
    }

    /** Generates a dummy image to be painted on the frame **/
    private static BufferedImage generateImage() {
        JLabel label = new JLabel("test");
        label.setSize(label.getPreferredSize());
        return getImage(label);
    }

    //Enable these lines for case 2
//    public void paint(Graphics g) {
//        super.paint(g);
//        g.drawImage(test, p.x, p.y, this);
//    }

    public class TranslucentPane extends JPanel {
        public TranslucentPane() {
            setOpaque(false);
        }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            Graphics2D g2d = (Graphics2D) g.create();
//            g2d.setComposite(AlphaComposite.SrcOver.derive(0.85f));
            g2d.setColor(new Color(0,0,0,0));
            g2d.fillRect(0, 0, getWidth(), getHeight());
            g2d.drawImage(test, p.x, p.y, this);
        }
    }    
}

The code is inspired from this question

Result:

Result

Sharcoux
  • 5,546
  • 7
  • 45
  • 78
  • You really shouldn't call `paint` on components, instead, using `printAll`, apart from disabling double buffering, it can cause issues if the component isn't attached to a native peer – MadProgrammer Sep 18 '17 at 07:11
  • I changed `c.paint(g);` to `c.printAll(g);` and added `g.dispose();` after it and run your example and it works fine for me - MacOS 10.12.6 and Java 8 – MadProgrammer Sep 18 '17 at 07:13
  • Wait, you changed `c.paint(g);` to `c.printAll(g);g.dispose();` in the `getImage` method and it worked? If that's it, it didn't work for me I'm afraid... – Sharcoux Sep 18 '17 at 07:47
  • Then it’s an issue with the jvm and OS – MadProgrammer Sep 18 '17 at 08:08

0 Answers0