如何在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); } }
关键细节说明
- 坐标变换处理:通过
mapFromItem和QTransform将其他item的完整变换(旋转、缩放、平移)转换到自身坐标系,再映射到离屏pixmap的局部坐标系,确保旋转后的图像区域绘制精准。 - 离屏渲染隔离:使用独立的
QPixmap和QPainter处理重叠混合,完全不影响主painter中的底层图像,避免了CompositionMode_Clear的副作用。 - 裁剪路径优化:通过
setClipPath限定绘制范围,只渲染重叠区域内的像素,提升渲染效率。
内容的提问来源于stack exchange,提问作者Filippo M. Libardi
相关产品推荐
相关产品推荐

