将 QSlider 移动到鼠标点击位置

Eam*_*onn 5 python pyqt qslider python-3.x pyqt5

我有一个 QSlider,当用户按下鼠标左键时,我想移动到鼠标光标的位置。我一直在四处寻找,找不到任何最近解决了我的问题的东西。

进度条

这是我的滑块。我希望能够点击让滑块跳转到鼠标点击的位置。我可以拖动滑块,但我希望能够点击。我测试了单击 Dolphin 文件管理器中的滑块。它增加而不是跳到鼠标的确切位置。

查看Qt5 文档

QSlider 很少有自己的功能 [...]

这表明没有内置的方法可以做到这一点。有没有办法找到鼠标点击的位置并将滑块移动到那个点?

eyl*_*esc 7

解决方法是计算位置并在mousePressEvent中设置,计算不像算术计算那么容易,因为它取决于每个操作系统的样式和样式表,所以我们必须使用QStyle,如下所示:

from PyQt5 import QtCore, QtWidgets


class Slider(QtWidgets.QSlider):
    def mousePressEvent(self, event):
        super(Slider, self).mousePressEvent(event)
        if event.button() == QtCore.Qt.LeftButton:
            val = self.pixelPosToRangeValue(event.pos())
            self.setValue(val)

    def pixelPosToRangeValue(self, pos):
        opt = QtWidgets.QStyleOptionSlider()
        self.initStyleOption(opt)
        gr = self.style().subControlRect(QtWidgets.QStyle.CC_Slider, opt, QtWidgets.QStyle.SC_SliderGroove, self)
        sr = self.style().subControlRect(QtWidgets.QStyle.CC_Slider, opt, QtWidgets.QStyle.SC_SliderHandle, self)

        if self.orientation() == QtCore.Qt.Horizontal:
            sliderLength = sr.width()
            sliderMin = gr.x()
            sliderMax = gr.right() - sliderLength + 1
        else:
            sliderLength = sr.height()
            sliderMin = gr.y()
            sliderMax = gr.bottom() - sliderLength + 1;
        pr = pos - sr.center() + sr.topLeft()
        p = pr.x() if self.orientation() == QtCore.Qt.Horizontal else pr.y()
        return QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), p - sliderMin,
                                               sliderMax - sliderMin, opt.upsideDown)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QWidget()
    flay = QtWidgets.QFormLayout(w)
    w1 = QtWidgets.QSlider(QtCore.Qt.Horizontal)
    w2 = Slider(QtCore.Qt.Horizontal)
    flay.addRow("default: ", w1)
    flay.addRow("modified: ", w2)
    w.show()
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!有用。最好在 mousePressEvent 中发出 sliderPressed 信号(我已经编辑了帖子)。另外,理想情况下,它应该被“按下”(即变得可拖动),直到鼠标释放。否则,只有在第一次单击后释放左键后才需要拖动它。如果您知道该怎么做,请更新。 (2认同)
  • 您只需将 super(Slider, self).mousePressEvent(event) 移动到 if 语句之后(缩进块之外)即可获得该行为。 (2认同)