如何阻止paintEvent绘制子部件?

1 投票
2 回答
1065 浏览
提问于 2025-04-18 00:36

我想给一个 QDialog 添加圆角。我正在定义自己的 paintEvent 方法来实现这个效果。现在效果是有了,但问题是它把圆角加到了所有东西上,连光标都被加上了边框。有没有办法关闭这种行为呢?

下面是示例代码:

from PySide import QtCore, QtGui


class RenameDialog(QtGui.QDialog):
    def __init__(self, parent=None, **kwargs):
        super(RenameDialog, self).__init__(
            parent=parent, f=QtCore.Qt.CustomizeWindowHint)
        self.fieldA = QtGui.QLineEdit(self)
        self.fieldB = QtGui.QLineEdit(self)

        self.setLayout(QtGui.QHBoxLayout())
        self.layout().addWidget(self.fieldA)
        self.layout().addWidget(self.fieldB)

        # Set background transparent.  Only items drawn in paintEvent
        # will be visible.
        palette = QtGui.QPalette()
        palette.setColor(QtGui.QPalette.Base, QtCore.Qt.transparent)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setPalette(palette)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        fillColor = QtGui.QColor(75, 75, 75, 255)
        lineColor = QtCore.Qt.gray

        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(QtGui.QPen(QtGui.QBrush(lineColor), 2.0))
        painter.setBrush(QtGui.QBrush(fillColor))
        painter.drawRoundedRect(event.rect(), 15, 15)

我之所以使用 paintEvent 是因为:

  • QDialog 的样式表不能使用 border-radius。虽然可以看到圆形的边框,但角落还是很明显。
  • QDialogs.setMask() 可以用,但我不知道怎么让这个遮罩变得更平滑。

这就是效果:

到处都是边框

2 个回答

0

我找到了一种临时解决办法。你可以通过对子控件使用 QPainter.eraseRect 来隐藏多余的边框,同时确保样式表设置正确。我还发现,用 QPainter.fillRect 在有问题的区域上涂色也能解决这个问题。

def paintEvent(self, event):
    painter = QtGui.QPainter(self)
    fillColor = QtGui.QColor(75, 75, 75, 255)
    lineColor = QtCore.Qt.gray

    painter.setRenderHint(QtGui.QPainter.Antialiasing)
    painter.setPen(QtGui.QPen(QtGui.QBrush(lineColor), 2.0))
    painter.setBrush(QtGui.QBrush(fillColor))
    painter.drawRoundedRect(event.rect(), 15, 15)

    # Sketchy fix:
    painter.eraseRect(self.childrenRect())
    # OR
    painter.fillRect(self.childrenRect(), QtGui.QBrush(fillColor))

不过,这并没有回答我最初的问题。我希望能避免这种情况,而不是简单地遮盖它。所以我不会把这个当作答案。

3

绘制事件会发送给窗口或小部件,告诉它具体哪个区域需要更新,而不是整个小部件的边界区域。当你调用 event.rect() 时,它会返回需要更新的那个矩形区域(据我所知是这样的)。

试着把这一行 painter.drawRoundedRect(event.rect(), 15, 15) 改成这样 painter.drawRoundedRect(self.rect(), 15, 15)

编辑: 你还需要在构造函数的任何地方添加这一行 self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

在这里输入图片描述

希望这对你有帮助。

撰写回答