简体   繁体   English

Java Swing:透明PNG永久捕获原始背景

[英]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. 目的是创建一个半透明的窗口,类似于Windows Aero风格的玻璃。 I have the following transparent png that I am using: http://i.imgur.com/5UNGbsr.png 我正在使用以下透明png: 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. 截屏时,我已经最小化了可以在后台看到的命令提示符和IDE,但仍保留在窗口的背景中。

What am I doing wrong? 我究竟做错了什么?

Don't override the paint() method of a top level container, especially when you don't invoke super.paint(). 不要覆盖顶级容器的paint()方法,尤其是当您不调用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. 如果确实需要进行自定义绘制,则应重写JPanel(或JComponent)的paintComponent()方法,然后将面板添加到窗口/框架。 Read the Swing tutorial on Custom Painting. 阅读有关“自定义绘画”的Swing教程。 This advice is given daily, I don't know why people still try to override paint()??? 每天都会提供此建议,我不知道为什么人们仍然尝试覆盖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. 更好的解决方案是将图像添加到JLabel,然后将标签添加到窗口。 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. Java仍然认为Window是不透明的,因此不会更新图形以显示实际的内容。

Creating a transparent window is relatively simple in Java since Java 1.6.10 (I think) 从Java 1.6.10开始,在Java中创建透明窗口相对简单(我认为)

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 基本上,您所需要做的就是将图像渲染代码放置在TestPanepaintComponent方法中

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();
            }
        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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