from PyQt6.QtWidgets import QSlider, QToolTip from PyQt6.QtCore import Qt class ClickableSlider(QSlider): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._get_tooltip_text = None self.setMouseTracking(True) def set_tooltip_provider(self, provider_func): self._get_tooltip_text = provider_func def mousePressEvent(self, event): super().mousePressEvent(event) if event.button() == Qt.MouseButton.LeftButton: val = 0 if self.orientation() == Qt.Orientation.Horizontal: if self.width() > 0: val = self.minimum() + ((self.maximum() - self.minimum()) * event.pos().x()) / self.width() else: if self.height() > 0: val = self.minimum() + ((self.maximum() - self.minimum()) * (self.height() - event.pos().y())) / self.height() val = max(self.minimum(), min(self.maximum(), int(val))) self.setValue(val) self.sliderMoved.emit(val) if self._get_tooltip_text: text = self._get_tooltip_text(val) if text: QToolTip.showText(event.globalPosition().toPoint(), text, self) def mouseMoveEvent(self, event): super().mouseMoveEvent(event) if self._get_tooltip_text and self.width() > 0: hover_val = self.minimum() + ((self.maximum() - self.minimum()) * event.pos().x()) / self.width() hover_val = max(self.minimum(), min(self.maximum(), int(hover_val))) text = self._get_tooltip_text(hover_val) if text: QToolTip.showText(event.globalPosition().toPoint(), text, self) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.button() == Qt.MouseButton.LeftButton: # Explicitly emit sliderReleased on mouse release # to ensure single clicks on the track also trigger the release logic self.sliderReleased.emit()