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

如何在QGraphicsItem中实现支持旋转的重叠区域半透明效果?

Qt自定义QGraphicsPixmapItem旋转后重叠区域半透明实现方案

问题分析

你遇到的两个核心问题:

  • 第一种方案旋转后失效:旋转后mapFromItem得到的重叠路径是自身坐标系下的,但直接裁剪原始未旋转的pixmap区域,会和路径位置错位,导致绘制异常。
  • 第二种方案出现黑色背景:CompositionMode_Clear会清除painter当前缓冲区的所有内容,包括底层其他图像的像素,最终露出默认黑色背景。

解决方案

采用离屏渲染+完整坐标变换的方式,先在独立的离屏pixmap中绘制好重叠区域的半透明混合效果,再将其绘制到主painter上。既解决旋转后的坐标错位问题,又不会破坏底层图像内容。

完整实现代码

void CustomGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    // 先绘制自身原始图像
    QGraphicsPixmapItem::paint(painter, option, widget);
    painter->setRenderHint(QPainter::Antialiasing);

    auto collidingItems = this->collidingItems();
    for (auto item : qAsConst(collidingItems)) {
        if (item == this) continue;
        auto otherItem = qgraphicsitem_cast<CustomGraphicsPixmapItem*>(item);
        if (!otherItem) continue;

        // 1. 将其他item的形状转换到自身坐标系下
        QPainterPath otherShapeInLocal = mapFromItem(otherItem, otherItem->shape());
        QPainterPath overlapPath = shape().intersected(otherShapeInLocal);
        if (overlapPath.isEmpty()) continue;

        QRectF overlapRect = overlapPath.boundingRect();
        // 2. 创建离屏pixmap,大小匹配重叠区域边界
        QPixmap overlayPixmap(overlapRect.size().toSize());
        overlayPixmap.fill(Qt::transparent);

        QPainter overlayPainter(&overlayPixmap);
        overlayPainter.setRenderHint(QPainter::Antialiasing);
        // 裁剪出重叠区域,只绘制该范围内的像素
        overlayPainter.setClipPath(overlapPath.translated(-overlapRect.topLeft()));

        // 3. 绘制自身的重叠区域(0.5透明度)
        QTransform selfToOverlay = QTransform::fromTranslate(-overlapRect.left(), -overlapRect.top()) 
                                 * transform().inverted();
        overlayPainter.setTransform(selfToOverlay);
        overlayPainter.setOpacity(0.5);
        overlayPainter.drawPixmap(pos(), pixmap());

        // 4. 绘制其他item的重叠区域(0.5透明度)
        QTransform otherToSelf = mapFromItem(otherItem, QPointF()).transform();
        QTransform otherToOverlay = QTransform::fromTranslate(-overlapRect.left(), -overlapRect.top()) 
                                 * otherToSelf * otherItem->transform();
        overlayPainter.setTransform(otherToOverlay);
        overlayPainter.setOpacity(0.5);
        overlayPainter.drawPixmap(otherItem->pos(), otherItem->pixmap());

        // 5. 将离屏渲染好的半透明区域绘制到主painter
        painter->drawPixmap(overlapRect.topLeft(), overlayPixmap);
    }
}

关键细节说明

  1. 坐标变换处理:通过mapFromItem和QTransform将其他item的完整变换(旋转、缩放、平移)转换到自身坐标系,再映射到离屏pixmap的局部坐标系,确保旋转后的图像区域绘制精准。
  2. 离屏渲染隔离:使用独立的QPixmap和QPainter处理重叠混合,完全不影响主painter中的底层图像,避免了CompositionMode_Clear的副作用。
  3. 裁剪路径优化:通过setClipPath限定绘制范围,只渲染重叠区域内的像素,提升渲染效率。

内容的提问来源于stack exchange,提问作者Filippo M. Libardi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 11:18:10