Решение состоит в том, чтобы сделать расчет позиции и установить ее в 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_())