首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有透明梯度的QGraphicsPixmapItem

具有透明梯度的QGraphicsPixmapItem
EN

Stack Overflow用户
提问于 2022-05-24 13:16:31
回答 1查看 108关注 0票数 0

我想在一个QGraphicsPixmapItem上应用一个透明梯度,但是我不知道如何去做,因为现在我只能在整个QGraphicsPixmapItem上应用透明性(不是梯度)。这个项目经历了一个镜像效应(就像墙上的一个反射在地面上的元素),然后我想设置这个透明梯度(从上到下;顶部相当不透明……)在透明的几个阶段,它最终在项目的底部是完全透明的),然后我添加模糊。这是透明梯度的一部分,我似乎做不到.我不明白它怎么能起作用。我试过的一切都不管用。你能帮我吗?提前谢谢。

下面是一个相当短的代码:

代码语言:javascript
复制
for item in self.scene.selectedItems() :
    # Width
    item_height = item.boundingRect().height()
    # mirroir
    item.setTransform(QTransform(1, 0, 0, 0, -1, 0, 0, 0, 1))
    # 
    item.setOpacity(0.7)
    # Blur
    blur = QGraphicsBlurEffect()
    blur.setBlurRadius(8)
    item.setGraphicsEffect(blur)
    item.setPos(100, 100 + 2 * (int(item_height)))
    ##############################################
    """
    alphaGradient = QLinearGradient(item.boundingRect().topLeft(), item.boundingRect().bottomLeft())
    alphaGradient.setColorAt(0.0, Qt.transparent)
    alphaGradient.setColorAt(0.5, Qt.black)
    alphaGradient.setColorAt(1.0, Qt.transparent)
    effect = QGraphicsOpacityEffect()
    effect.setOpacityMask(alphaGradient)
    item.setGraphicsEffect(effect) ########
    """
    ##############################################
    """
    opacity = QGraphicsOpacityEffect()
    lg = QLinearGradient()
    lg.setStart(0, 0)
    lg.setFinalStop(0, 100)
    lg.setColorAt(0, Qt.transparent)
    lg.setColorAt(0.5, Qt.transparent)
    lg.setColorAt(1.0, Qt.transparent)
    opacity.setOpacityMask(lg)
    #opacity.setOpacity(1)
    item.setGraphicsEffect(opacity)
    """
    ##############################################
EN

回答 1

Stack Overflow用户

发布于 2022-05-24 15:13:11

每个目标项(或小部件)只能应用一个QGraphicsEffect,因此您有两个选项:

  • 创建一个新的图像,应用不透明梯度(使用QPainter组合模式),并只设置模糊效果;
  • 设置父项的不透明度效果;

在这两种情况下,我建议您将“镜像”项创建为实际QGraphicsPixmapItem的子项,这将确保它始终遵循父级发生的情况,包括可见性和几何更改、转换等。

使用透明梯度生成镜像

为此,我们使用了作文的QPainter特性,特别是允许使用梯度作为所绘制图像的alpha通道的源的CompositionMode_SourceIn

程序如下:

  1. 根据镜像的大小创建一个新的图像;
  2. 创建一个渐变,具有完全不透明度在0和透明在1(或更少);
  3. 在图像上画出梯度;
  4. 设定构图模式;
  5. 绘制镜像;
  6. 创建基于该图像的QGraphicsPixmapItem;
代码语言:javascript
复制
class MirrorPixmapItem(QtWidgets.QGraphicsPixmapItem):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.mirror = QtWidgets.QGraphicsPixmapItem(self)
        self.blurEffect = QtWidgets.QGraphicsBlurEffect(blurRadius=8)
        self.mirror.setGraphicsEffect(self.blurEffect)
        if not self.pixmap().isNull():
            self.createMirror()

    def setPixmap(self, pixmap):
        old = self.pixmap()
        super().setPixmap(pixmap)
        if old == pixmap:
            return
        self.createMirror()

    def setOffset(self, *args):
        super().setOffset(*args)
        if not self.mirror.pixmap().isNull():
            self.mirror.setOffset(self.offset())

    def createMirror(self):
        source = self.pixmap()
        if source.isNull():
            self.mirror.setPixmap(source)
            return

        scale = .5
        height = int(source.height() * scale)

        output = QtGui.QPixmap(source.width(), height)
        output.fill(QtCore.Qt.transparent)

        qp = QtGui.QPainter(output)
        grad = QtGui.QLinearGradient(0, 0, 0, height)
        grad.setColorAt(0, QtCore.Qt.black)
        grad.setColorAt(1, QtCore.Qt.transparent)
        qp.fillRect(output.rect(), grad)
        qp.setCompositionMode(qp.CompositionMode_SourceIn)
        qp.drawPixmap(0, 0, 
            source.transformed(QtGui.QTransform().scale(1, -scale)))
        qp.end()

        self.mirror.setPixmap(output)
        self.mirror.setY(self.boundingRect().bottom())
        self.mirror.setOffset(self.offset())

设置父项的不透明度。

在这种情况下,我们仍然对镜像项有模糊效果,但是我们在父项(原始映像)上应用了一个QGraphicsOpacityEffect,并使用了包含原始图像和镜像的opacityMask,它将处于完全不透明状态,直到原始图像的高度,然后开始淡出到镜像的完全透明。

代码语言:javascript
复制
class MirrorPixmapItem2(QtWidgets.QGraphicsPixmapItem):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.opacity = QtWidgets.QGraphicsOpacityEffect(opacity=1)
        self.setGraphicsEffect(self.opacity)
        self.mirror = QtWidgets.QGraphicsPixmapItem(self)
        self.blurEffect = QtWidgets.QGraphicsBlurEffect(blurRadius=8)
        self.mirror.setGraphicsEffect(self.blurEffect)
        if not self.pixmap().isNull():
            self.createMirror()

    # ... override setPixmap() and setOffset() as above

    def createMirror(self):
        source = self.pixmap()
        if source.isNull():
            self.mirror.setPixmap(source)
            return

        scale = .5

        self.mirror.setPixmap(
            source.transformed(QtGui.QTransform().scale(1, -scale)))
        self.mirror.setPos(self.boundingRect().bottomLeft())
        self.mirror.setOffset(self.offset())

        height = source.height()
        gradHeight = height + height * scale

        grad = QtGui.QLinearGradient(0, 0, 0, gradHeight)
        grad.setColorAt(height / gradHeight, QtCore.Qt.black)
        grad.setColorAt(1, QtCore.Qt.transparent)
        self.opacity.setOpacityMask(grad)

这就是结果,正如您可以看到的,使用哪种方法是一个选择的问题,但是从性能的角度来看,第一个方法可能会稍微好一些,因为在绘制项目时不需要额外的效果,如果要有许多图像项和/或高分辨率,这可能很重要。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72363586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档