Files
Feeding_control_system/view/widgets/arc_progress_widget.py

291 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QWidget, QVBoxLayout, QSizePolicy
from PySide6.QtGui import QPixmap
from PySide6.QtCore import Qt, QPropertyAnimation, Property
import os
import resources.resources_rc
from utils.image_paths import ImagePaths
# 拱形进度条
class OverlapArcProgress(QWidget):
def __init__(self, bg_img_path, fg_img_path, parent=None):
super().__init__(parent)
self._progress = 0 # 进度0-100
self.setStyleSheet("background: transparent; border: none;")
# 加载并统一图片尺寸
self.bg_pixmap = QPixmap(bg_img_path)
self.fg_pixmap = QPixmap(fg_img_path)
if self.bg_pixmap.isNull():
print(f"错误:拱进度条背景图 {bg_img_path} 加载失败")
if self.fg_pixmap.isNull():
print(f"错误:拱进度条前景图 {fg_img_path} 加载失败")
if self.bg_pixmap.size() != self.fg_pixmap.size():
self.fg_pixmap = self.fg_pixmap.scaled(
self.bg_pixmap.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
)
# 控件尺寸与图片一致(避免缩放失真)
self.setFixedSize(self.bg_pixmap.size())
self.total_height = self.bg_pixmap.height() # 缓存总高度(背景/前景高度一致)
# 背景标签(下层,完整显示背景)
self.bg_label = QLabel(self)
self.bg_label.setPixmap(self.bg_pixmap)
self.bg_label.setScaledContents(False) # 禁用缩放
# 前景标签(上层,初始加载完整前景图,通过高度控制显示区域)
self.fg_label = QLabel(self)
self.fg_label.setPixmap(self.fg_pixmap) # 直接加载完整前景图
self.fg_label.setScaledContents(False) # 禁用缩放(避免图片拉伸)
self.fg_label.setAlignment(Qt.AlignBottom) # 图片在标签内底部对齐
self.fg_label.raise_() # 确保在背景上层
# 初始状态高度为0位置在底部不显示任何内容
self.fg_label.setGeometry(0, self.total_height, self.bg_pixmap.width(), 0)
# ---------- 进度显示标签 ----------
# self.progress_label = QLabel(self)
# self.progress_label.setGeometry(217, 17, 121, 34)
# self.progress_label.setStyleSheet("""
# background-color: #444750;
# color: #A2EF4D;
# font-size: 20px;
# font-weight: bold;
# """)
# # 文本在标签内部居中显示
# self.progress_label.setAlignment(Qt.AlignCenter)
# self.progress_label.raise_() # 确保在前景上层(最上层)
# self.progress_label.setText("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):
"""通过调整前景标签的高度和Y坐标, 实现从底部向上填充的进度条"""
# 同步更新进度标签文本
# self.progress_label.setText(f"{self._progress}%")
# print(f"{self._progress}%")
progress_ratio = self._progress / 100.0
k = 8 # 调整此系数k越大“快慢差异”越明显推荐范围 3~10
# 公式height_ratio = x + k*(x³/3 - x²/2 + x/6)
height_ratio = progress_ratio + k * (
(progress_ratio ** 3) / 3 -
(progress_ratio ** 2) / 2 +
progress_ratio / 6
)
height_ratio = max(0.0, min(1.0, height_ratio)) # 限制范围0-1
# 计算目标高度(随进度变化)
target_height = int(self.total_height * height_ratio)
# fg_label标签Y坐标 = 总高度 - 目标高度(实现底部对齐,向上延伸)
target_y = self.total_height - target_height
# 标签宽度与背景一致,高度为目标高度
self.fg_label.setGeometry(
0, # X坐标与背景左对齐
target_y, # Y坐标底部对齐
self.bg_pixmap.width(), # 宽度(与背景一致)
target_height # 高度(随进度变化)
)
class ArcProgressWidget(QWidget):
def __init__(self):
super().__init__()
# 加载ArcProgressWidget背景图
# 添加了 拱3.png 作为背景图
bg_img = ImagePaths.ARCH3 # 需要修改为实际的图片的路径
# self.setStyleSheet(f"background-image: url({bg_img}); background-repeat: no-repeat; background-position: center;")
self.bg_pixmap = QPixmap(bg_img)
# self.setStyleSheet("background-color: red;")
# # 设置控件widget大小与背景图一致
# self.bg_pixmap.size() 为 555x227
# self.setFixedSize(self.bg_pixmap.size())
# self.setFixedSize(555, 254)
self.setFixedSize(555, 259)
self.setSizePolicy(
QSizePolicy.Fixed, # 水平方向固定
QSizePolicy.Fixed # 垂直方向固定
)
# 创建垂直主布局
main_layout = QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0) # 去除边距
main_layout.setSpacing(0) # 去除控件间距
# 1. 添加标题标签(保持居中)
self.arc_title_label = QLabel("振捣模具车", self)
self.arc_title_label.setFixedSize(555, 29)
self.arc_title_label.setAlignment(Qt.AlignCenter)
self.arc_title_label.setStyleSheet(f"""
color: #0bffff;
font-size: 18px;
background-image: url({ImagePaths.TEXT_TITLE_BG});
background-repeat: no-repeat;
background-position: center;
margin: 4px auto;
""")
main_layout.addWidget(self.arc_title_label, alignment=Qt.AlignCenter)
# 2. 创建普通QWidget作为容器大小与背景图一致
container = QWidget(self)
container.setFixedSize(self.bg_pixmap.size()) # 容器大小=背景图大小
# 容器内设置背景图
background_label = QLabel(container)
background_label.setPixmap(self.bg_pixmap)
background_label.setScaledContents(True)
background_label.setFixedSize(container.size())
background_label.lower() # 背景置底,避免遮挡其他控件
# 3. 在容器内添加所有标签和拱形进度条用setGeometry定位
# 创建拱形进度条控件
arc_bg_img = ImagePaths.ARCH2 # 替换为实际路径
arc_fg_img = ImagePaths.ARCH1 # 替换为实际路径
self.arc_progress = OverlapArcProgress(arc_bg_img, arc_fg_img, container)
# 显示环号的标签
self.ring_number_label = QLabel("环号: 1", container)
self.ring_number_label.setGeometry(98, 118, 116, 29) # 保持原坐标
self.ring_number_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.ring_number_label.setAlignment(Qt.AlignCenter)
# 显示重量的标签
self.weight_label = QLabel("2000kg", container)
self.weight_label.setGeometry(217, 118, 118, 29) # 保持原坐标
self.weight_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.weight_label.setAlignment(Qt.AlignCenter)
# 显示管片型号的标签
self.segment_model_label = QLabel("中埋: R12", container)
self.segment_model_label.setGeometry(98, 150, 116, 29)
self.segment_model_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.segment_model_label.setAlignment(Qt.AlignCenter)
# 显示频率的标签
self.frequency_label = QLabel("210Hz", container)
self.frequency_label.setGeometry(217, 150, 118, 29)
self.frequency_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.frequency_label.setAlignment(Qt.AlignCenter)
# 显示管片编号的标签
self.segment_number_label = QLabel("SHRB1-3", container)
self.segment_number_label.setGeometry(338, 150, 116, 29)
self.segment_number_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.segment_number_label.setAlignment(Qt.AlignCenter)
# 显示管片尺寸的标签
self.segment_size_label = QLabel("6900*1500", container)
self.segment_size_label.setGeometry(98, 182, 116, 29)
self.segment_size_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.segment_size_label.setAlignment(Qt.AlignCenter)
# 显示状态的标签
self.state_label = QLabel("振动中", container)
self.state_label.setGeometry(217, 182, 118, 29)
self.state_label.setStyleSheet("""
background-color: #143a6e;
color: #16ffff;
font-size: 18px;
""")
self.state_label.setAlignment(Qt.AlignCenter)
# 4. 将拱形进度条容器添加到主布局
main_layout.addWidget(container, alignment=Qt.AlignCenter)
# 进度条测试
def testProgress(self, seconds: float):
# 启动动画从0%到100% (模拟进度加载)
self.animation = QPropertyAnimation(self.arc_progress, b"progress")
self.animation.setDuration(seconds * 1000)
self.animation.setStartValue(0)
self.animation.setEndValue(100)
self.animation.start()
# 进度条设置
def setProgress(self, progress:int):
"""
设置progress之后, 会根据该值调整进度条
Args:
progress: 传入去掉百分号之后的数值, 如80%, 传入80
"""
try:
if isinstance(progress, str):
progress = progress.strip().replace("%", "")
progress_int = int(float(progress))
progress_int = max(0, min(100, progress_int))
self.arc_progress.progress = progress_int
except (ValueError, TypeError):
pass # 传入的生产进度类型错误,维持原进度
# 重量设置 (单位kg)
def setWeight(self, weight:float):
self.weight_label.setText(f"{weight}kg")
# 频率设置单位Hz
def setFrequency(self, frequency:float):
self.frequency_label.setText(f"{frequency}Hz")
# 状态设置 (...中)
def setState(self, stateStr:str):
self.state_label.setText(stateStr)
# 管片类型设置 (B1、B2、中埋: R12 等)
def setSegmentModel(self, segmentModelStr:str):
self.segment_model_label.setText(segmentModelStr)
# 管片编号设置
def setSegmentNumber(self, segmentNumberStr:str):
self.segment_number_label.setText(segmentNumberStr)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = ArcProgressWidget()
window.testProgress(120)
# window.setState("测试中")
window.show()
sys.exit(app.exec())