JSwing无装饰窗口已设透明属性但背景仍不透明求助
透明背景虚拟宠物窗口显示问题解决
我想把一张青蛙图片显示在屏幕上,背景设为透明,作为虚拟宠物程序的测试。复制了相关代码实现,但运行后图片出现黑色背景,原代码如下:
// Java Program to implement the shaped window import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.io.*; import javax.imageio.*; class solve extends JFrame { public static void main(String[] args) { try { JWindow w = new JWindow(); w.setBackground(new Color(0, 0, 0, 0)); BufferedImage i = ImageIO.read(new File("froge.png")); JPanel p = new JPanel() { public void paintComponent(Graphics g) { for (int ii = 1; ii < i.getHeight(); ii++) for (int j = 1; j < i.getWidth(); j++) { Color ty = new Color(i.getRGB(j, ii)); if (ty.getRed() > 200 && ty.getGreen() > 200 && ty.getBlue() > 200) g.setColor(new Color(0, 0, 0, 0)); else g.setColor(new Color(i.getRGB(j, ii))); g.drawLine(j, ii, j, ii); } } }; w.add(p); w.setLocation(350, 300); w.setSize(1120, 320); w.setVisible(true); } catch (Exception e) { System.err.println(e.getMessage()); } } }
问题原因及解决方法
JPanel默认不透明
JPanel默认会绘制自身灰色背景,在透明窗口下会被渲染为黑色。必须给面板添加p.setOpaque(false);,让面板不绘制自身背景,才能透出窗口的透明效果。逐像素绘制效率低且存在边界错误
原代码从ii=1和j=1开始循环,会丢失图片第一行第一列的像素;且逐像素绘制的方式性能极差。直接使用g.drawImage()绘制图片是更高效、可靠的方案:- 若原图片是带透明通道的PNG,直接绘制即可;
- 若原图片是白色背景,先将白色区域转为透明再绘制。
修正后的代码
// Java Program to implement the shaped window import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.io.*; import javax.imageio.*; class solve extends JFrame { public static void main(String[] args) { try { JWindow w = new JWindow(); w.setBackground(new Color(0, 0, 0, 0)); // 读取原始图片并处理透明通道 BufferedImage originalImage = ImageIO.read(new File("froge.png")); BufferedImage transparentImage = new BufferedImage( originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_INT_ARGB // 支持透明通道的图片类型 ); Graphics2D g2d = transparentImage.createGraphics(); g2d.drawImage(originalImage, 0, 0, null); g2d.dispose(); // 将白色区域转为透明 for (int y = 0; y < transparentImage.getHeight(); y++) { for (int x = 0; x < transparentImage.getWidth(); x++) { Color c = new Color(transparentImage.getRGB(x, y)); if (c.getRed() > 200 && c.getGreen() > 200 && c.getBlue() > 200) { transparentImage.setRGB(x, y, new Color(0, 0, 0, 0).getRGB()); } } } JPanel p = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 确保组件绘制流程正常 g.drawImage(transparentImage, 0, 0, this); } }; p.setOpaque(false); // 设置面板透明 w.add(p); w.setLocation(350, 300); w.setSize(transparentImage.getWidth(), transparentImage.getHeight()); // 匹配图片尺寸 w.setVisible(true); } catch (Exception e) { System.err.println(e.getMessage()); } } }
额外说明
- 窗口尺寸直接使用图片实际大小,避免多余的空白透明区域;
- 调用
super.paintComponent(g)确保组件的绘制生命周期完整,避免出现绘制异常; - 使用
BufferedImage.TYPE_INT_ARGB类型存储处理后的图片,保证透明通道生效。
内容的提问来源于stack exchange,提问作者Slomas99
相关产品推荐
相关产品推荐

