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

Java Swing实现拖拽透明矩形框显示模糊图局部清晰图的方法

实现Swing拖拽透明框显示清晰图像的方案

核心思路

利用JLayeredPane的层级特性,将清晰图放在最底层,中间层用自定义组件绘制模糊图并在透明框位置“挖洞”透出清晰图,最上层放置可拖拽的透明框,拖拽时触发中间层重绘更新显示区域。

具体实现步骤

1. 组件层级规划

将三个组件按顺序添加到JLayeredPane:

  • 最底层(层级值Integer.MIN_VALUE):清晰图像的JLabel,铺满整个容器作为背景
  • 中间层(层级值0):自定义JLabel,负责绘制模糊图像,并根据透明框位置清除对应区域的模糊图,透出底层清晰图
  • 最上层(层级值Integer.MAX_VALUE):透明矩形框的JLabel,已添加鼠标拖拽监听器

2. 自定义模糊图绘制组件

重写JLabel的paintComponent方法,在绘制完整模糊图后,清除透明框所在区域的图像:

import javax.swing.*;
import java.awt.*;

public class BlurredImageView extends JLabel {
    private final Image blurredImage;
    private final JLabel boxLabel;

    public BlurredImageView(ImageIcon blurredIcon, JLabel boxLabel) {
        this.blurredImage = blurredIcon.getImage();
        this.boxLabel = boxLabel;
        setOpaque(false); // 必须设为透明,否则会遮挡底层清晰图
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (blurredImage == null || boxLabel == null) return;

        Graphics2D g2d = (Graphics2D) g.create();
        try {
            // 绘制全屏模糊图
            g2d.drawImage(blurredImage, 0, 0, getWidth(), getHeight(), this);
            // 获取透明框当前位置
            Rectangle boxRect = boxLabel.getBounds();
            // 清除框内的模糊图,让底层清晰图透出
            g2d.setComposite(AlphaComposite.Clear);
            g2d.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height);
        } finally {
            g2d.dispose();
        }
    }
}

3. 完善透明框的拖拽逻辑

在已有的鼠标监听器中,添加位置更新后的重绘触发,同时限制拖拽范围避免超出容器:

// 假设透明框JLabel实例为boxLabel
boxLabel.addMouseListener(new MouseAdapter() {
    private int offsetX, offsetY;

    @Override
    public void mousePressed(MouseEvent e) {
        // 记录鼠标按下时相对框的偏移量
        offsetX = e.getX();
        offsetY = e.getY();
    }
});

boxLabel.addMouseMotionListener(new MouseMotionAdapter() {
    @Override
    public void mouseDragged(MouseEvent e) {
        JLayeredPane parent = (JLayeredPane) boxLabel.getParent();
        int newX = boxLabel.getX() + e.getX() - offsetX;
        int newY = boxLabel.getY() + e.getY() - offsetY;

        // 限制拖拽范围,防止框超出容器边界
        newX = Math.max(0, Math.min(newX, parent.getWidth() - boxLabel.getWidth()));
        newY = Math.max(0, Math.min(newY, parent.getHeight() - boxLabel.getHeight()));

        boxLabel.setLocation(newX, newY);
        // 触发模糊图组件重绘,更新透出区域
        parent.getComponent(1).repaint(); // 或者直接持有blurredLabel实例调用repaint()
    }
});

4. 初始化容器与组件

// 初始化JLayeredPane
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(800, 600)); // 按实际图像尺寸设置

// 加载图像
ImageIcon clearIcon = new ImageIcon("path/to/clear-image.jpg");
ImageIcon blurredIcon = new ImageIcon("path/to/blurred-image.jpg");
ImageIcon boxIcon = new ImageIcon("path/to/transparent-box.png");

// 创建清晰图组件
JLabel clearLabel = new JLabel(clearIcon);
clearLabel.setBounds(0, 0, layeredPane.getWidth(), layeredPane.getHeight());
layeredPane.add(clearLabel, Integer.MIN_VALUE);

// 创建透明框组件
JLabel boxLabel = new JLabel(boxIcon);
boxLabel.setBounds(100, 100, boxIcon.getIconWidth(), boxIcon.getIconHeight());
// 添加上述的鼠标监听器到boxLabel...
layeredPane.add(boxLabel, Integer.MAX_VALUE);

// 创建模糊图组件
BlurredImageView blurredLabel = new BlurredImageView(blurredIcon, boxLabel);
blurredLabel.setBounds(0, 0, layeredPane.getWidth(), layeredPane.getHeight());
layeredPane.add(blurredLabel, 0);

// 将layeredPane添加到JFrame
JFrame frame = new JFrame();
frame.add(layeredPane);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

关键注意事项

  • 所有组件必须手动设置bounds,因为JLayeredPane默认使用null布局
  • 模糊图组件必须设置setOpaque(false),否则会完全遮挡底层的清晰图
  • 透明框的PNG需保证中间区域完全透明,才能正常显示下方的清晰图
  • 拖拽时限制边界,避免透明框移出容器导致显示异常

内容的提问来源于stack exchange,提问作者ezpzzzz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:51:32