PyQt6 在 QSlider 的 paintEvent 中设置自定义矩形

PyQt6 Setting custom rect in QSlider's paintEvent

如何让 QSlider 的 paintEvent 的 rect 变小一点?我想要一个非常薄的滑块,但我希望它能够轻松接收点击,因此它的实际尺寸必须比绘制的尺寸大一点。如果滑块真的很薄,例如 2 个像素,那么尝试抓住手柄或单击它会很烦人。我尝试在 paintEvent 方法中创建自定义 QPaintEvent 并使其矩形高度等于 1-2,然后将其传递给 super().paintEvent(my_new_paint_event) 但它没有用。如何做到这一点?

除了使用 QSS(需要设置 all 属性的样式)之外,唯一可靠的解决方案是使用代理样式。

虽然可以覆盖滑块的 paintEvent(),但有两个主要问题:

  • 更改事件区域完全没有意义,因为它只会更改函数将利用的公开区域(并且该区域也可能会被完全忽略);
  • QSlider 的默认 paintEvent() 会在调用样式函数之前根据当前状态和 active/hovered 子控件更新其选项,除非您愿意覆盖一堆其他函数(enter/leave、鼠标 press/move/release、键盘事件等),您只会得到部分有效的结果,不会反映实际的小部件状态;

QSlider 使用 drawComplexControl() function of QStyle, and this is achieved by providing a set of flags used for the subControls and activeSubControls of QStyleOptionSlider.

绘制自己

由于这些控件之一是 SC_SliderGroove,它是手柄在其上移动的滑块部分,解决方案是将其从 subControls 中删除,然后在您的自己的。请记住,绘画是从下到上进行的,因此必须在 调用基本实现之前 绘制自定义凹槽。

class Style(QtWidgets.QProxyStyle):
    def drawComplexControl(self, control, opt, qp, widget=None):
        if control == self.CC_Slider:
            # get the default rectangle of the groove
            groove = self.subControlRect(
                control, opt, self.SC_SliderGroove, widget)
            # create a small one
            if opt.orientation == QtCore.Qt.Horizontal:
                rect = QtCore.QRectF(
                    groove.x(), groove.center().y() - .5, 
                    groove.width(), 2)
            else:
                rect = QtCore.QRectF(
                    groove.center().x() - .5, groove.y(), 
                    2, groove.height())
            qp.save()
            qp.setBrush(opt.palette.mid())
            qp.setPen(opt.palette.dark().color())
            qp.setRenderHints(qp.Antialiasing)
            qp.drawRoundedRect(rect, 1, 1)
            qp.restore()

            # remove the groove flag from the subcontrol list
            opt.subControls &= ~self.SC_SliderGroove

        super().drawComplexControl(control, opt, qp, widget)

以上是 PyQt5 和 PySide 通用的,对于 PyQt6,您需要使用它们的类型更改标志名称,如 Qt.Orientation.Horizontal,等