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

我有以下代码:

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

目的是创建一个半透明的窗口,类似于Windows Aero风格的玻璃。 我有以下透明的png: http : //i.imgur.com/5UNGbsr.png

问题是,由于它透明,它假设显示窗口后面的东西,对吧? 这就是它首次执行时所做的事情,除了首次启动时这个“透明窗口”后面的窗口,程序以某种方式创建了一个“图像”并永久地将其与窗口连接。 因此,即使我最小化这个“透明窗口”后面的窗口,第一个背景窗口的图像仍然存在。

这是一个截图:

在此处输入图像描述

当我拍摄这个屏幕截图时,我已经最小化了命令提示符和可以在后台看到的IDE,但它仍然保留在窗口的背景中。

我究竟做错了什么?

不要覆盖顶级容器的paint()方法,尤其是在不调用super.paint()时。 这将导致绘画问题。 如果您确实需要进行自定义绘制,则应覆盖JPanel(或JComponent)的paintComponent()方法,然后将面板添加到窗口/框架中。 阅读自定义绘画的Swing教程。 这个建议是每天给出的,我不知道为什么人们仍然试图覆盖paint()???

然而,这只是你的一个问题。 更好的解决方案是将图像添加到JLabel,然后将标签添加到窗口。 您还需要使窗口背景透明:

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

问题是,你的窗口实际上是透明的。 Java仍然认为Window不透明,因此不会更新图形,以显示实际背后的内容。

自Java 1.6.10(我认为)以来,在Java中创建透明窗口相对简单

以下是一个非常简单的示例,使用半透明的绘画效果,允许永远落在窗口下方的画面继续正确绘制。

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

更新图像示例

屏幕拍摄显示窗户被移到窗户后面……

在此处输入图像描述在此处输入图像描述

基本上,您需要做的就是将图像渲染代码放在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(); } } } }