代码之家  ›  专栏  ›  技术社区  ›  kairom13

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

  •  0
  • kairom13  · 技术社区  · 4 年前

    我的应用程序使用QGridLayout中排列的各种QGroupBox来显示信息。我想其中一个显示自定义形状,我画。由于我希望形状是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_()
    

    Window with paint event enabled

    Window with paint event commented out

    1 回复  |  直到 4 年前
        1
  •  0
  •   musicamante    4 年前

    您正在覆盖 绘画,“覆盖”意味着你 忽视 默认行为。

    的默认行为 paintEvent() 对标准Qt小部件的修改会导致绘制该小部件(无论是按钮、标签、组框等)。如果你只是覆盖它,那个小部件就会 从不 涂漆, 除非 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)

    也就是说,你可能想画画 在…内 因此,更好的解决方案是为 目录 在该groupbox中,将其添加到groupbox,并替代该子类的绘制事件。

    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)