简体   繁体   中英

Java Swing: Transparent PNG permanently captures original background

I have the following code:

import javax.swing.JWindow;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

public class sutff extends JWindow
{
    //Get transparent image that will be use as splash screen image.
    Image bi=Toolkit.getDefaultToolkit().getImage("window.png");
    ImageIcon ii=new ImageIcon(bi);
    public sutff()
    {
        try
        {
            setSize(ii.getIconWidth(),ii.getIconHeight());
            setLocationRelativeTo(null);
            show();
            //Thread.sleep(10000);
            //dispose();
            //JOptionPane.showMessageDialog(null,"This program will exit !!!","<>",JOptionPane.INFORMATION_MESSAGE);
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
    }
    //Paint transparent image onto JWindow
    public void paint(Graphics g)
    {
        g.drawImage(bi,0,0,this);
    }
    public static void main(String[]args)
    {
        sutff tss=new sutff();
    }
}

The purpose is to create a window that is translucent and resembles Windows Aero-style glass. I have the following transparent png that I am using: http://i.imgur.com/5UNGbsr.png

The problem is that since its transparent, its suppose to show the things behind the window, right? That's what it does when first executed, except whatever window is behind this "transparent window" when it first starts up, the program somehow creates an "image" of that and permanently attaches it with the window. So even if I minimize the windows behind this "transparent window," the image of the first background window remains.

Here is a screenshot:

在此处输入图片说明

When I took this screen shot, I had already minimized the command prompt and the IDE which can be seen in the background, yet it still remains in the background of the window.

What am I doing wrong?

Don't override the paint() method of a top level container, especially when you don't invoke super.paint(). This will cause painting problems. If you ever do need to do custom painting then you should override the paintComponent() method of JPanel (or JComponent) and then add the panel to the window/frame. Read the Swing tutorial on Custom Painting. This advice is given daily, I don't know why people still try to override paint()???

However this is only one of your problems. The better solution is to add your image to a JLabel and then add the label to the window. You will also need to make the window background transparent:

import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.Image;
import java.awt.Toolkit;

public class Stuff extends JWindow
{
    //Get transparent image that will be use as splash screen image.
    Image bi=Toolkit.getDefaultToolkit().getImage("transparent.png");
    ImageIcon ii=new ImageIcon(bi);
    public Stuff()
    {
        try
        {
            setBackground( new Color(0, 0, 0, 0) );
            setSize(ii.getIconWidth(),ii.getIconHeight());
            setLocationRelativeTo(null);
            JLabel label = new JLabel(ii);
            add(label);
            show();
            //Thread.sleep(10000);
            //dispose();
            //JOptionPane.showMessageDialog(null,"This program will exit !!!","<>",JOptionPane.INFORMATION_MESSAGE);
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
    }

/*
    //Paint transparent image onto JWindow
    public void paint(Graphics g)
    {
        super.paint(g);
        g.drawImage(bi,0,0,this);
    }
*/
    public static void main(String[]args)
    {
        Stuff tss=new Stuff();
    }
}

The problem is, you window is actually transparent. Java still thinks that the Window opaque and therefore won't update the graphics in such away as to show what's actually behind.

Creating a transparent window is relatively simple in Java since Java 1.6.10 (I think)

The following is a very simple example, using a semi transparent paint effect that will allow what ever falls below the window to continue to be painted correctly.

import com.sun.awt.AWTUtilities;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TransaprentBlur {

    public static void main(String[] args) {
        new TransaprentBlur();
    }

    public TransaprentBlur() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setUndecorated(true);
                frame.setBackground(new Color(0, 0, 0, 0));
//                Java 6...
//                AWTUtilities.setWindowOpaque(frame, true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setOpaque(false);

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        System.exit(0);
                    }
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Shape shape = new RoundRectangle2D.Float(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(new Color(225, 225, 225, 128));
            g2d.fill(shape);
            g2d.setColor(Color.GRAY);
            g2d.draw(shape);
            g2d.dispose();
        }

    }

}

Update with image example

Screen shoots showing windows been moved behind the window...

在此处输入图片说明在此处输入图片说明

Basically, all you need to do, is place you image rendering code with in the paintComponent method of TestPane

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TransaprentBlur {

    public static void main(String[] args) {
        new TransaprentBlur();
    }

    public TransaprentBlur() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setUndecorated(true);
                frame.setBackground(new Color(0, 0, 0, 0));
//                Java 6...
//                AWTUtilities.setWindowOpaque(frame, true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage image;

        public TestPane() {

            try {
                image = ImageIO.read(getClass().getResource("/5UNGbsr.png"));
            } catch (IOException ex) {
            }
            setOpaque(false);

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        System.exit(0);
                    }
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (image != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - image.getWidth()) / 2;
                int y = (getHeight() - image.getHeight()) / 2;
                g2d.drawImage(image, x, y, this);
                g2d.dispose();
            }
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM