如何使用 QPainter 绘制带有动态“孔”/负空间的半透明叠加层?

问题描述 投票:0回答:1

我有这样的图像:

我有一个自定义小部件,它重新实现了

paintEvent()

在图像的顶部,我想绘制一个覆盖层,并保留一个或多个矩形。具有圆角和适当的抗锯齿功能。

我猜这可能通过 QPainter::CompositionMode 实现。但如何呢?也许将覆盖层绘制到 QImage 中?颠倒过来?

在paint.net中,我在第二层中画了一个矩形,然后用魔术棒选择了内部,并将其删除。我不知道如何用 QPainter 做到这一点。

qt qt5
1个回答
0
投票

使用合成模式是可能的,但这需要完全理解它们的行为(坦率地说,我从来无法理解它们)。

此外,在使用像素图时,通常还需要进一步的步骤,即在临时“缓冲区”(另一个 QPixmap 或 QImage)上绘制其中一个图层。

只要“遮罩”很简单,它不涉及多个图像的 Alpha 混合,并且图像是不透明的(根本没有透明度),我们可以遵循更简单的路径,即绘画over并最终通过剪切内容来“清除”所需区域。

程序其实很简单:

  1. 绘制像素图;
  2. 用“阴影”颜色填充整个区域;
  3. 创建一个 QPainterPath() 并添加我们需要“清晰”的所有区域;
  4. 在 QPainter 上使用
    setClipPath()
    (设置了
    Antialiasing
    渲染提示);
  5. 再次绘制像素图;

我不会用C++编写,但是下面Python中的简单示例应该足够清楚了:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class ClipTest(QWidget):
    def __init__(self):
        super().__init__()
        # This is the original image used in the question
        self.pixmap = QPixmap('baseimage.png')
        self.setFixedSize(self.pixmap.size())

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.setRenderHint(qp.Antialiasing)
        qp.drawPixmap(0, 0, self.pixmap)

        # draw the darker "shade" on the whole widget
        qp.fillRect(self.rect(), QColor(32, 32, 32, 127))

        path = QPainterPath()
        # add a couple of rounded rects, which are also colliding
        path.addRoundedRect(250, 110, 140, 140, 20, 20)
        path.addRoundedRect(380, 110, 140, 140, 20, 20)

        # to fill all enclosed regions, including those of colliding
        # sub paths that may be otherwise be unpainted
        path.setFillRule(Qt.WindingFill)

        # clip the painting on the path above
        qp.setClipPath(path)

        # redraw the pixmap again
        qp.drawPixmap(0, 0, self.pixmap)


app = QApplication([])
win = Test()
win.show()
app.exec()

给出以下结果:

© www.soinside.com 2019 - 2024. All rights reserved.