I'm having a problem with the QSlider element in PyQt5. Below is a simplified version of my code that only calls the slider. I have two methods: One to print the slider value when it is moving, and one to print the slider value once the user releases the button.
If you drag the slider to a position (let's say 10) and hold it there, it should print out 10. If you release it, it will print out 11 (if you dragged from the left-hand side) or it will print out 9 (if you dragged from the right-hand side.
I'm really at a loss for why it is off by 1 depending on which direction the slider is moved. I would like the two methods to print off the same number.
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QSlider
from PyQt5.QtCore import Qt
import sys
class GUIWindow(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(300, 0, 900, 900)
# Slider
self.eventSlider = QSlider(Qt.Horizontal)
self.eventSlider.setFixedWidth(600)
self.eventSlider.setSingleStep(1)
self.eventSlider.setValue(0)
self.eventSlider.setMinimum(0)
self.eventSlider.setMaximum(20)
self.eventSlider.setTickInterval(1)
self.eventSlider.setTickPosition(QSlider.TicksBelow)
self.eventSlider.sliderMoved.connect(self.slider_changing)
self.eventSlider.sliderReleased.connect(self.slider_changed)
GUILayout = QGridLayout()
GUILayout.setContentsMargins(0, 0, 0, 0)
GUILayout.addWidget(self.eventSlider, 0, 0, 1, 9, alignment=Qt.AlignCenter)
self.setLayout(GUILayout)
def slider_changing(self):
print(self.eventSlider.value())
def slider_changed(self):
print(self.eventSlider.value())
if __name__ == '__main__':
app = QApplication(sys.argv)
window = GUIWindow()
window.show()
sys.exit(app.exec_())
You are confused by the mechanism of QAbstractSlider (which is the base class for widgets like QSlider).
Let's see the explanation in the documentation.
QAbstractSlider.sliderMoved(value)
:
This signal is emitted when sliderDown is true and the slider moves. This usually happens when the user is dragging the slider. The value is the new slider position.
QAbstractSlider.valueChanged(value)
This signal is emitted when the slider value has changed, with the new slider value as argument.
The difference is that the sliderMoved
signal is emitted when the slider is moved, not when the value is changed.
In fact, if you disable the tracking
, you'll see that the slider_changing
will always print the same current value, until the slider is released.
That's what happens when tracking is disabled (the default):
sliderPressed
is emitted, at this point the value and the position are still the same, 0sliderMoved
signal is emitted, now the slider position is at 1, but the value is still at 0valueChanged
signal is emittedSince you're checking the currentValue
within the sliderMoved
signal connection, at that point the value has not been updated.
To get the actual value when the slider is moved you've two options:
sliderPosition()
instead of currentValue
(or, better, get the parameter of sliderMoved
, which already contains the new position (and possible new value, no matter if tracking is enabled or not);valueChanged()
;