This commit is contained in:
Your Name
2026-08-13 11:54:00 +08:00
parent 07188e82f8
commit 72a5300b08
19 changed files with 1441 additions and 577 deletions
+52 -9
View File
@@ -10,13 +10,12 @@ from datetime import date, datetime
from typing import Any
from PySide6.QtCore import QObject, QRunnable, Qt, QThreadPool, QTimer, Signal, Slot
from PySide6.QtGui import QResizeEvent
from PySide6.QtGui import QColor, QPainter, QPaintEvent, QResizeEvent
from PySide6.QtWidgets import (
QAbstractItemView,
QFrame,
QHBoxLayout,
QLabel,
QProgressBar,
QPushButton,
QSizePolicy,
QTableWidget,
@@ -543,30 +542,74 @@ def show_toast(parent: QWidget, text: str, kind: str = "info", duration: int = 2
toast.show_message(text, kind, duration)
class _BusyTrack(QWidget):
"""Indeterminate bar painted in-process, without Windows QProgressBar HWNDs.
``QProgressBar.setRange(0, 0)`` uses the native Vista/Win11 animation, which
creates extra untitled windows titled with the application name.
"""
def __init__(self, parent: QWidget) -> None:
super().__init__(parent)
self.setObjectName("BusyOverlayProgress")
self.setFixedSize(140, 6)
self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
self._phase = 0.0
self._timer = QTimer(self)
self._timer.setInterval(32)
self._timer.timeout.connect(self._tick)
def showEvent(self, event: Any) -> None:
self._timer.start()
super().showEvent(event)
def hideEvent(self, event: Any) -> None:
self._timer.stop()
super().hideEvent(event)
def _tick(self) -> None:
self._phase = (self._phase + 0.035) % 1.0
self.update()
def paintEvent(self, event: QPaintEvent) -> None: # noqa: N802 - Qt API
del event
painter = QPainter(self)
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
painter.setPen(Qt.PenStyle.NoPen)
rect = self.rect()
painter.setBrush(QColor("#D8DEEA"))
painter.drawRoundedRect(rect, 3, 3)
chunk_width = max(36, int(rect.width() * 0.32))
span = rect.width() + chunk_width
x = int(self._phase * span) - chunk_width
painter.setBrush(QColor("#4F63D9"))
painter.drawRoundedRect(x, 0, chunk_width, rect.height(), 3, 3)
class BusyOverlay(QFrame):
"""Non-blocking visual guard for a card or page while a worker is active."""
def __init__(self, parent: QWidget, text: str = "正在加载…") -> None:
super().__init__(parent)
self.setObjectName("BusyOverlay")
self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
layout = QVBoxLayout(self)
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.setSpacing(10)
self.label = QLabel(text)
self.label = QLabel(text, self)
self.label.setProperty("role", "muted")
progress = QProgressBar()
progress.setObjectName("BusyOverlayProgress")
progress.setRange(0, 0)
progress.setFixedWidth(140)
self.progress = _BusyTrack(self)
layout.addWidget(self.label, 0, Qt.AlignmentFlag.AlignCenter)
layout.addWidget(progress, 0, Qt.AlignmentFlag.AlignCenter)
layout.addWidget(self.progress, 0, Qt.AlignmentFlag.AlignCenter)
self.hide()
def set_message(self, text: str) -> None:
self.label.setText(text)
def showEvent(self, event: Any) -> None:
self.setGeometry(self.parentWidget().rect())
parent = self.parentWidget()
if parent is not None:
self.setGeometry(parent.rect())
self.raise_()
super().showEvent(event)