Compare commits

...
1 Commits
Author SHA1 Message Date
Dervart 9ca924c70f feat: smooth AutoHideScrollArea 2026-07-01 17:18:34 +07:00
+63 -2
View File
@@ -1,6 +1,6 @@
from PySide6.QtWidgets import QLabel, QPushButton, QStyle, QStyleOptionButton, QWidget, QLayout, QLayoutItem, QScrollArea, QGraphicsOpacityEffect
from PySide6.QtCore import Qt, Signal, QRect, QRectF, QSize, Property, QPropertyAnimation, QEasingCurve, QTimer, QEvent
from PySide6.QtGui import QFont, QFontMetrics, QIcon, QPainter
from PySide6.QtGui import QFont, QFontMetrics, QIcon, QPainter, QWheelEvent
from PySide6.QtSvg import QSvgRenderer
from portprotonqt.theme_manager import ThemeManager
from portprotonqt.config import ui_config
@@ -724,6 +724,9 @@ class AutoHideScrollArea(QScrollArea):
parent: QWidget | None = None,
hide_delay_ms: int = 1000,
fade_duration_ms: int = 200,
invert_wheel: bool = True,
wheel_scroll_factor: float = 20.0, # новый параметр
wheel_animation_duration: int = 500, # новый параметр
):
self.theme = theme
self.theme_manager = ThemeManager()
@@ -731,6 +734,9 @@ class AutoHideScrollArea(QScrollArea):
super().__init__(parent)
self.hide_delay_ms = hide_delay_ms
self.fade_duration_ms = fade_duration_ms
self.invert_wheel = invert_wheel
self._wheel_scroll_factor = wheel_scroll_factor
self._wheel_animation_duration = wheel_animation_duration
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
self.setStyleSheet("background: transparent;")
@@ -762,6 +768,9 @@ class AutoHideScrollArea(QScrollArea):
if initial_widget is not None:
initial_widget.installEventFilter(self)
# Анимация скролла (для колёсика)
self._scroll_anim = None
QTimer.singleShot(0, self._update_scroll_needed)
def _apply_visible_style(self) -> None:
@@ -815,6 +824,58 @@ class AutoHideScrollArea(QScrollArea):
self._start_fade_in()
self._hide_timer.start(self.hide_delay_ms)
# ---------- ПЕРЕОПРЕДЕЛЯЕМ wheelEvent С УЧЁТОМ НОВЫХ ПАРАМЕТРОВ ----------
def wheelEvent(self, event: QWheelEvent) -> None:
if not self._scroll_needed:
event.ignore()
return
delta = event.angleDelta().y()
if delta == 0:
event.ignore()
return
scrollbar = self.verticalScrollBar()
current_value = scrollbar.value()
# Базовый шаг с учётом коэффициента скорости
step = scrollbar.singleStep() * self._wheel_scroll_factor
# Определяем направление с учётом инверсии
if self.invert_wheel:
if delta > 0:
step = -step
else:
if delta < 0:
step = -step
target = current_value + step
target = max(scrollbar.minimum(), min(scrollbar.maximum(), target))
if target == current_value:
event.accept()
return
# Останавливаем предыдущую анимацию
if self._scroll_anim is not None:
self._scroll_anim.stop()
self._scroll_anim.deleteLater()
self._scroll_anim = None
self._scroll_anim = QPropertyAnimation(scrollbar, b"value")
self._scroll_anim.setDuration(self._wheel_animation_duration) # используется новый параметр
self._scroll_anim.setStartValue(current_value)
self._scroll_anim.setEndValue(target)
self._scroll_anim.setEasingCurve(QEasingCurve.Type.OutCubic)
self._scroll_anim.start()
if not self._is_visible:
self._start_fade_in()
self._hide_timer.start(self.hide_delay_ms)
event.accept()
# ---------- ОСТАЛЬНЫЕ МЕТОДЫ ----------
def enterEvent(self, event):
if self._scroll_needed:
self._start_fade_in()
@@ -846,7 +907,7 @@ class AutoHideScrollArea(QScrollArea):
old_widget.removeEventFilter(self)
if widget is None:
super().setWidget(None) # type: ignore
super().setWidget(None)
else:
super().setWidget(widget)
widget.installEventFilter(self)