将QSlider移至鼠标单击位置

时间:2018-10-07 13:39:42

标签: python python-3.x pyqt pyqt5 qslider

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

Progress Bar

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

看着Qt5 documentation

  

QSlider几乎没有自己的功能[...]

这表明没有内置方法可以执行此操作。没有办法获得鼠标单击的位置并将滑块移至该点?

2 个答案:

答案 0 :(得分:3)

解决方案是对位置进行计算并在mousePressEvent中进行设置,由于算术运算取决于每个OS和样式表的样式,因此作为算术运算并不容易,因此我们必须使用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_())

答案 1 :(得分:2)

QSlider不具有此功能,因此实现此功能的唯一方法是编写自定义窗口小部件并覆盖其中的鼠标单击:

class Slider(QSlider):

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            e.accept()
            x = e.pos().x()
            value = (self.maximum() - self.minimum()) * x / self.width() + self.minimum()
            self.setValue(value)
        else:
            return super().mousePressEvent(self, e)

请注意,此代码仅适用于水平滑块。