2025-10-18 18:29:40 +08:00
|
|
|
|
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
|
2025-10-31 18:52:31 +08:00
|
|
|
|
from PySide6.QtGui import QPixmap, QRegion, QPainter, QColor, QPainterPath
|
2025-10-18 18:29:40 +08:00
|
|
|
|
from PySide6.QtCore import Qt, QPropertyAnimation, Property, QSize, QRectF
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
class MaskedLabel(QLabel):
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
|
super().__init__(parent)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.setFixedSize(28, 20) # 遮罩大小
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.setStyleSheet("background-color: transparent; border: none;")
|
|
|
|
|
|
|
|
|
|
|
|
def paintEvent(self, event):
|
|
|
|
|
|
painter = QPainter(self)
|
|
|
|
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
|
|
|
|
|
# parent_widget = self.parent()
|
|
|
|
|
|
bg_color = QColor("#023eab") # 默认颜色 注意:需要根据背景颜色修改
|
|
|
|
|
|
# if parent_widget:
|
|
|
|
|
|
# # 从父控件的调色板中提取背景色
|
|
|
|
|
|
# bg_color = parent_widget.palette().color(parent_widget.backgroundRole())
|
|
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
# 用父控件背景色绘制遮罩
|
|
|
|
|
|
painter.setBrush(bg_color)
|
|
|
|
|
|
painter.setPen(Qt.NoPen)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
# 步骤3:绘制遮罩路径(逻辑不变)
|
|
|
|
|
|
path = QPainterPath()
|
|
|
|
|
|
mask_rect = QRectF(0, 0, 28, 20)
|
|
|
|
|
|
circle_radius = 10
|
|
|
|
|
|
circle_center_x = 28
|
|
|
|
|
|
circle_center_y = 10
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
path.addRect(mask_rect)
|
|
|
|
|
|
path.addEllipse(
|
|
|
|
|
|
circle_center_x - circle_radius,
|
|
|
|
|
|
circle_center_y - circle_radius,
|
|
|
|
|
|
circle_radius * 2,
|
2025-10-31 18:52:31 +08:00
|
|
|
|
circle_radius * 2,
|
2025-10-18 18:29:40 +08:00
|
|
|
|
)
|
|
|
|
|
|
path.setFillRule(Qt.OddEvenFill)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
painter.drawPath(path)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
class LinearProductionProgress(QWidget):
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
|
self._progress = 0 # 进度(0-100)
|
|
|
|
|
|
self.setFixedSize(450 + 18, 20)
|
|
|
|
|
|
self.setStyleSheet(
|
2025-10-31 18:52:31 +08:00
|
|
|
|
"""
|
2025-10-18 18:29:40 +08:00
|
|
|
|
border-radius: 9px;
|
|
|
|
|
|
"""
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 底层背景
|
|
|
|
|
|
self.bg_label = QLabel(self)
|
|
|
|
|
|
self.bg_label.setFixedSize(450, 20)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
# self.bg_label.setStyleSheet(
|
|
|
|
|
|
# """
|
|
|
|
|
|
# background-color: #e7e7e7;
|
|
|
|
|
|
# """
|
|
|
|
|
|
# )
|
|
|
|
|
|
# #011454
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.bg_label.setStyleSheet(
|
2025-10-31 18:52:31 +08:00
|
|
|
|
"""
|
|
|
|
|
|
background-color: #011454;
|
2025-10-18 18:29:40 +08:00
|
|
|
|
"""
|
|
|
|
|
|
)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.bg_label.move(17, 0) # 这里需要调整对齐
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
# 上层进度填充
|
|
|
|
|
|
self.fg_label = QLabel(self)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
# self.fg_label.setStyleSheet(
|
|
|
|
|
|
# """
|
|
|
|
|
|
# background-color: #0052d9;
|
|
|
|
|
|
# min-width: 18px;
|
|
|
|
|
|
# """
|
|
|
|
|
|
# )
|
|
|
|
|
|
# #02f2fe
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.fg_label.setStyleSheet(
|
|
|
|
|
|
"""
|
2025-10-31 18:52:31 +08:00
|
|
|
|
background-color: #02f2fe;
|
2025-10-18 18:29:40 +08:00
|
|
|
|
min-width: 18px;
|
|
|
|
|
|
"""
|
|
|
|
|
|
)
|
|
|
|
|
|
self.fg_label.setFixedHeight(20)
|
|
|
|
|
|
self.fg_label.move(0, 0)
|
|
|
|
|
|
self.fg_label.raise_()
|
|
|
|
|
|
|
|
|
|
|
|
# 百分比标签(宽33px,高19px,右偏9px)
|
|
|
|
|
|
self.percent_label = QLabel(self)
|
|
|
|
|
|
self.percent_label.setText("0%")
|
|
|
|
|
|
self.percent_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
self.percent_label.setFixedSize(33, 19)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
# self.percent_label.setStyleSheet(
|
|
|
|
|
|
# """
|
|
|
|
|
|
# color: white;
|
|
|
|
|
|
# font-size: 12px;
|
|
|
|
|
|
# font-weight: bold;
|
|
|
|
|
|
# background-color: transparent;
|
|
|
|
|
|
# """
|
|
|
|
|
|
# )
|
|
|
|
|
|
# #02366c #001c83
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.percent_label.setStyleSheet(
|
|
|
|
|
|
"""
|
2025-10-31 18:52:31 +08:00
|
|
|
|
color: #001c83;
|
|
|
|
|
|
font-size: 13px;
|
2025-10-18 18:29:40 +08:00
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
|
"""
|
|
|
|
|
|
)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.percent_label.move(18, 0) # 百分比标签初始位置
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.percent_label.raise_()
|
|
|
|
|
|
|
|
|
|
|
|
# 遮盖左侧区域
|
|
|
|
|
|
self.mask_label = MaskedLabel(self)
|
|
|
|
|
|
self.mask_label.move(0, 0)
|
|
|
|
|
|
|
|
|
|
|
|
# 进度属性
|
|
|
|
|
|
@Property(int)
|
|
|
|
|
|
def progress(self):
|
|
|
|
|
|
return self._progress
|
|
|
|
|
|
|
|
|
|
|
|
@progress.setter
|
|
|
|
|
|
def progress(self, value):
|
|
|
|
|
|
if 0 <= value <= 100 and value != self._progress:
|
|
|
|
|
|
self._progress = value
|
|
|
|
|
|
self.update_foreground()
|
|
|
|
|
|
|
|
|
|
|
|
# 线性更新进度显示
|
|
|
|
|
|
def update_foreground(self):
|
|
|
|
|
|
# 注意:为了实现前4%的动态效果,需要从 fd_width的4%起开始计算
|
|
|
|
|
|
fg_width = int(450 * (self._progress + 4) / 100)
|
|
|
|
|
|
self.fg_label.setFixedWidth(fg_width)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
# 计算百分比标签位置:进度条右边缘 - 9px(偏移) - 标签宽度(33px)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
if fg_width > 60: # 当上层进度条宽度大于60px,开始移动
|
|
|
|
|
|
label_x = fg_width - 9 - 33
|
2025-10-18 18:29:40 +08:00
|
|
|
|
# 移动百分比标签
|
|
|
|
|
|
self.percent_label.move(label_x, 0)
|
|
|
|
|
|
else:
|
|
|
|
|
|
# 复原百分比标签
|
|
|
|
|
|
# 移动回初始位置
|
|
|
|
|
|
self.percent_label.move(18, 0)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
# 设置百分比标签
|
|
|
|
|
|
self.percent_label.setText(f"{self._progress}%")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ProductionProgressWidget(QWidget):
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
super().__init__()
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.setFixedSize(620, 49) # 进度条控件大小
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
# 左侧文字标签
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.text_label = QLabel("进度")
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.text_label.setFixedSize(112, 29)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.text_label.setAlignment(Qt.AlignTop | Qt.AlignRight)
|
|
|
|
|
|
self.text_label.setStyleSheet("font-family: 'Microsoft YaHei';font-size: 20px;color: #16FFFF;")
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
# 右侧进度条
|
|
|
|
|
|
self.linear_progress = LinearProductionProgress()
|
2025-10-31 18:52:31 +08:00
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.main_layout = QHBoxLayout(self)
|
|
|
|
|
|
self.main_layout.addWidget(self.text_label)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.main_layout.addWidget(self.linear_progress, alignment=Qt.AlignLeft)
|
2025-10-18 18:29:40 +08:00
|
|
|
|
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
2025-10-31 18:52:31 +08:00
|
|
|
|
self.main_layout.setSpacing(0)
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
def testProgress(self, seconds: float):
|
|
|
|
|
|
self.animation = QPropertyAnimation(self.linear_progress, b"progress")
|
|
|
|
|
|
self.animation.setDuration(seconds * 1000)
|
|
|
|
|
|
self.animation.setStartValue(0)
|
|
|
|
|
|
self.animation.setEndValue(100)
|
|
|
|
|
|
self.animation.start()
|
|
|
|
|
|
|
2026-01-16 18:37:21 +08:00
|
|
|
|
def setProgress(self, progress: int):
|
2025-10-18 18:29:40 +08:00
|
|
|
|
"""
|
|
|
|
|
|
设置progress之后, 会根据该值调整进度条
|
|
|
|
|
|
Args:
|
2026-01-16 18:37:21 +08:00
|
|
|
|
progress: 传入去掉百分号之后的数值, 如80%, 传入80
|
2025-10-18 18:29:40 +08:00
|
|
|
|
"""
|
2026-01-16 18:37:21 +08:00
|
|
|
|
try:
|
|
|
|
|
|
if isinstance(progress, str):
|
|
|
|
|
|
progress = progress.strip().replace("%", "")
|
|
|
|
|
|
progress_int = int(float(progress))
|
|
|
|
|
|
progress_int = max(0, min(100, progress_int))
|
|
|
|
|
|
self.linear_progress.progress = progress_int
|
|
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
|
|
pass # 生产进度更新失败,维持原进度
|
|
|
|
|
|
|
2025-10-18 18:29:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
app = QApplication(sys.argv)
|
|
|
|
|
|
window = ProductionProgressWidget()
|
2025-10-31 18:52:31 +08:00
|
|
|
|
window.testProgress(60) # 进度条测试
|
2025-10-18 18:29:40 +08:00
|
|
|
|
window.show()
|
|
|
|
|
|
sys.exit(app.exec())
|