繁体   English   中英

PyQt5:为什么QGroupBox的默认样式在绘画时会消失?

[英]PyQt5: Why does the default style of a QGroupBox disappear when painting?

我的应用程序使用排列在 QGridLayout 中的各种 QGroupBox 来显示信息。 我希望其中一个显示我绘制的自定义形状。 由于我希望形状是 GroupBox 并且很难获得小部件相对于窗口的位置,因此我决定将 GroupBox 子类化并将绘制事件添加到子类中。 这很好用,但是它完全消除了 GroupBox 的默认样式,包括标题。

下面的代码创建了一个带有两个 GroupBox 的简单窗口,一个使用标准类,一个使用子类中的绘制事件。 您应该看到右边的只有绘制的矩形,没有 GroupBox 样式。

如果您注释掉绘制事件,则 GroupBox 将照常显示。 为什么会发生这种情况,我应该怎么做才能保持 GroupBox 风格? 是否有另一种方法可以在不使用子类中的绘制事件的 GroupBox 中使用画家?

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


class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        ## Set up Window layout
        super(MainWindow, self).__init__(*args, **kwargs)

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setGeometry(300, 50, 1000, 700)

        leftGroup = QGroupBox('Left Group')
        self.layout.addWidget(leftGroup, 0, 0)

        rightGroup = RightGroup()
        self.layout.addWidget(rightGroup, 0, 1)


class RightGroup(QGroupBox):
    def __init__(self):
        super(RightGroup, self).__init__('Right Group')

    def paintEvent(self, event):
        painter = QPainter(self)

        # Paint Style
        painter.setPen(QPen(Qt.black, .5, Qt.SolidLine))

        painter.drawRect(QRectF(0, 0, self.width(), self.height()))


if __name__ == '__main__':
    ## Creates a QT Application
    app = QApplication([])

    ## Creates a window
    window = MainWindow()

    ## Shows the window
    window.show()
    app.exec_()

启用绘制事件的窗口

带有绘制事件的窗口被注释掉

您正在覆盖整个绘画,“覆盖”意味着您忽略默认行为。

标准 Qt 小部件的paintEvent()的默认行为导致绘制该小部件(无论是按钮、标签、组框等)。 如果您只是覆盖它,则该小部件将永远不会被绘制,除非您调用默认实现(即: super().paintEvent(event) )。

例如,考虑以下情况:

class RightGroup(QGroupBox):
    pass

这将正确显示一个正常的组框。

现在,这个:

class RightGroup(QGroupBox):
    def paintEvent(self, event):
        pass

不会显示任何内容,因为您明确忽略了默认绘画行为。 要“恢复”它添加自定义绘图:

class RightGroup(QGroupBox):
    def paintEvent(self, event):
        super().paintEvent(event)
        qp = QPainter(self)
        qp.drawRect(self.rect().adjusted(0, 0, -1, -1)

注意:除非您使用抗锯齿且笔宽小于或等于 0.5,否则应始终将对象矩形的右/下边缘限制为小于或等于笔宽一半的整数。 这就是上面adjusted(0, 0, -1, -1)的原因。 对于您上面的代码,它将是QRectF(0, 0, self.width() - 1, self.height() - 1)

也就是说,您可能希望该组框内绘图,因此,更好的解决方案是为该组框的内容创建一个子类,将其添加到该组框并覆盖该子类的绘制事件。

class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        # ...
        rightGroup = QGroupBox('Right Group')
        self.layout.addWidget(rightGroup, 0, 1)

        rightLayout = QVBoxLayout(rightGroup)
        rightLayout.addWidget(Canvas())


class Canvas(QWidget):
    def __init__(self):
        super().__init__()
        self.path = QPainterPath()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.path.moveTo(event.pos())

    def mouseMoveEvent(self, event):
        # note: here we use "buttons", not "button".
        if event.buttons() == Qt.LeftButton:
            self.path.lineTo(event.pos())
            self.update()

    def mouseReleaseEvent(self, event):
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHints(painter.Antialiasing)

        painter.setPen(QPen(Qt.black, .5, Qt.SolidLine))

        painter.drawRect(self.rect())

        painter.drawPath(self.path)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM