#!/usr/bin/python3 from PyQt6.QtCore import Qt from PyQt6.QtGui import QMouseEvent from PyQt6.QtWidgets import QSlider, QStyle, QStyleOptionSlider class TrackProgressSlider(QSlider): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dragged = False option = QStyleOptionSlider() style = self.style() self.handle_width = style.pixelMetric(QStyle.PixelMetric.PM_SliderThickness, option, self) self.sliderPressed.connect(self.on_press) self.sliderReleased.connect(self.on_release) def mousePressEvent(self, event: QMouseEvent): # we need a custom press event bc. PyQt doesn't set the slider position when clicked if event.button() == Qt.MouseButton.LeftButton: event.accept() x = event.pos().x() # old value calculation: # value = self.maximum() * x // self.width() # but we need that calculation because the handle width is limiting the range, and we need to set # the slider handle's center to the click position, not the start of the handle # (self.width() - self.handle_width) calculates the usable width and # (x - self.handle_width // 2) offsets the position by minus half of the handle width value = self.maximum() * (x - self.handle_width // 2) // (self.width() - self.handle_width) self.setValue(value) return super().mousePressEvent(event) def on_press(self): self.dragged = True def on_release(self): self.dragged = False