You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因及解决方法

  1. JPanel默认不透明
    JPanel默认会绘制自身灰色背景,在透明窗口下会被渲染为黑色。必须给面板添加p.setOpaque(false);,让面板不绘制自身背景,才能透出窗口的透明效果。

  2. 逐像素绘制效率低且存在边界错误
    原代码从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 04:30:41