Files
zjsh_ui_sysytem/main.py

485 lines
18 KiB
Python
Raw Normal View History

2025-09-10 18:07:58 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
# @Time : 2025/9/10 11:29
# @Author : reenrr
# @File : test.py
'''
2025-09-10 11:20:31 +08:00
import sys
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QFrame, QSizePolicy, QPushButton
)
2025-09-10 18:07:58 +08:00
from PySide6.QtCore import Qt, QTimer, QPoint, QSize
from PySide6.QtGui import QFont, QPainter, QColor, QPen, QIcon
2025-09-10 11:20:31 +08:00
from datetime import datetime
2025-09-10 18:07:58 +08:00
2025-09-10 11:20:31 +08:00
class StatusMonitor(QWidget):
"""
2025-09-10 18:07:58 +08:00
中交三航精准布料浇筑要料系统 - 主界面类深色主题
2025-09-10 11:20:31 +08:00
"""
def __init__(self, parent=None):
"""构造函数初始化主界面的UI布局、控件和定时器"""
super().__init__(parent=parent)
self.is_running = False # 系统运行状态标记
2025-09-10 18:07:58 +08:00
self.current_datetime = self.get_current_time() # 当前日期时间
2025-09-10 11:20:31 +08:00
# 窗口基础设置
self.setWindowTitle("中交三航精准布料浇筑要料系统")
2025-09-11 20:42:12 +08:00
self.setGeometry(100, 100, 850, 500) # 设置窗口位置和大小
2025-09-10 18:07:58 +08:00
self.setStyleSheet("background-color: #121212;") # 窗口背景设为深黑色
2025-09-10 11:20:31 +08:00
# 初始化主布局(垂直布局)
self.mainLayout = QVBoxLayout(self)
2025-09-10 18:07:58 +08:00
self.mainLayout.setContentsMargins(10, 40, 10, 10) # 上边距留空用于显示日期
self.mainLayout.setSpacing(10) # 相邻控件的间距
2025-09-10 11:20:31 +08:00
# 初始化界面组件
self._init_title_label()
self._init_status_container()
self._init_timers()
def _init_title_label(self):
"""初始化系统标题标签"""
titleLabel = QLabel("中交三航精准布料浇筑要料系统")
titleLabel.setStyleSheet("""
QLabel {
2025-09-10 18:07:58 +08:00
color: #00FF9D;
font-size: 20px;
2025-09-10 11:20:31 +08:00
font-weight: bold;
}
""")
titleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
titleLabel.setFont(QFont("Microsoft YaHei", 24, QFont.Bold))
self.mainLayout.addWidget(titleLabel)
def _init_status_container(self):
"""初始化核心状态监控容器(包含状态组和操作按钮)"""
self.bigContainer = QFrame()
self.bigContainer.setStyleSheet("""
QFrame {
2025-09-10 18:07:58 +08:00
background-color: #1E1E1E;
border: 2px solid #333333;
2025-09-10 11:20:31 +08:00
border-radius: 8px;
}
""")
self.bigContainer.setSizePolicy(
QSizePolicy.Policy.Expanding,
QSizePolicy.Policy.Expanding
)
containerLayout = QVBoxLayout(self.bigContainer)
containerLayout.setContentsMargins(20, 20, 20, 20)
self._init_status_groups(containerLayout)
self._init_operation_buttons(containerLayout)
self.mainLayout.addWidget(self.bigContainer, 1)
def _init_status_groups(self, parent_layout):
2025-09-10 18:07:58 +08:00
"""初始化左右信息各包含5个状态项"""
2025-09-10 11:20:31 +08:00
statusWidget = QWidget()
statusLayout = QHBoxLayout(statusWidget)
statusLayout.setContentsMargins(0, 0, 0, 0)
2025-09-11 20:42:12 +08:00
statusLayout.setSpacing(30) # 减小中间空白间距原30
2025-09-10 11:20:31 +08:00
leftGroup = QWidget()
leftLayout = QVBoxLayout(leftGroup)
leftLayout.setSpacing(15)
2025-09-11 20:42:12 +08:00
leftLayout.setContentsMargins(30, 0, 0, 0) # 左边组左内边距设为20增加左边留白
2025-09-10 11:20:31 +08:00
rightGroup = QWidget()
rightLayout = QVBoxLayout(rightGroup)
rightLayout.setSpacing(15)
2025-09-11 20:42:12 +08:00
rightLayout.setContentsMargins(0, 0, 30, 0) # 右边组右内边距设为20增加右边留白若需左边也留白可设左内边距
2025-09-10 11:20:31 +08:00
2025-09-10 18:07:58 +08:00
# 左边5个状态项及对应初始值
leftStatusInfo = [
{"name": "任务单号", "value": "20250706-01"},
{"name": "工程名称", "value": "18号线二期工程"},
2025-09-11 20:42:12 +08:00
{"name": "区间段", "value": "停车场工作并上行"},
{"name": "坍落度", "value": "50~70 mm"},
{"name": "配合比编号", "value": "P2022=001"}
2025-09-10 18:07:58 +08:00
]
# 右边5个状态项及对应初始值
rightStatusInfo = [
2025-09-11 20:42:12 +08:00
{"name": "要料状态", "value": "请求中"},
{"name": "要料标号", "value": "C50P12"},
{"name": "要料方量", "value": "2m³"},
{"name": "要料时间", "value": "2分钟后"},
{"name": "小车状态", "value": "移动后"}
2025-09-10 18:07:58 +08:00
]
2025-09-10 11:20:31 +08:00
self.statusWidgets = []
2025-09-10 18:07:58 +08:00
# 处理左边状态项
for info in leftStatusInfo:
2025-09-10 11:20:31 +08:00
statusItem = QFrame()
statusItem.setStyleSheet("""
QFrame {
2025-09-10 18:07:58 +08:00
background-color: #2D2D2D;
border: 1px solid #444444;
2025-09-10 11:20:31 +08:00
border-radius: 6px;
padding: 10px;
}
""")
statusItem.setFixedHeight(80)
2025-09-11 20:42:12 +08:00
statusItem.setFixedWidth(320) # 统一加长状态项宽度(原无固定宽度)
2025-09-10 11:20:31 +08:00
itemLayout = QHBoxLayout(statusItem)
itemLayout.setContentsMargins(10, 5, 10, 5)
# 状态指示灯
indicator = QLabel()
indicator.setFixedSize(20, 20)
indicator.setStyleSheet("""
QLabel {
background-color: #9E9E9E;
border-radius: 10px;
2025-09-10 18:07:58 +08:00
border: 2px solid #555555;
2025-09-10 11:20:31 +08:00
}
""")
# 状态名称标签
2025-09-10 18:07:58 +08:00
nameLabel = QLabel(info["name"])
2025-09-11 20:42:12 +08:00
nameLabel.setFixedWidth(100) # 加宽名称标签原90
nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
2025-09-10 18:07:58 +08:00
nameLabel.setStyleSheet("font-size: 14px; color: #FFFFFF;")
2025-09-10 11:20:31 +08:00
nameLabel.setFont(QFont("Microsoft YaHei", 12))
# 状态值标签
2025-09-10 18:07:58 +08:00
valueLabel = QLabel(info["value"])
2025-09-10 11:20:31 +08:00
valueLabel.setStyleSheet("""
QLabel {
2025-09-10 18:07:58 +08:00
font-size: 16px;
font-weight: bold;
color: #FFFFFF;
2025-09-11 20:42:12 +08:00
background-color: #2D2D2D;
border: none;
padding: 0px;
2025-09-10 18:07:58 +08:00
}
""")
valueLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
2025-09-11 20:42:12 +08:00
valueLabel.setMinimumWidth(150) # 加宽值标签原80
2025-09-10 18:07:58 +08:00
itemLayout.addWidget(indicator)
itemLayout.addSpacing(10)
itemLayout.addWidget(nameLabel)
itemLayout.addStretch()
itemLayout.addWidget(valueLabel)
self.statusWidgets.append({
'indicator': indicator,
'nameLabel': nameLabel,
'valueLabel': valueLabel,
'status': False,
'initial_value': info["value"]
})
leftLayout.addWidget(statusItem)
# 处理右边状态项
for info in rightStatusInfo:
statusItem = QFrame()
statusItem.setStyleSheet("""
QFrame {
background-color: #2D2D2D;
border: 1px solid #444444;
border-radius: 6px;
padding: 10px;
}
""")
statusItem.setFixedHeight(80)
2025-09-11 20:42:12 +08:00
statusItem.setFixedWidth(320) # 统一加长状态项宽度(与左侧一致)
2025-09-10 18:07:58 +08:00
itemLayout = QHBoxLayout(statusItem)
itemLayout.setContentsMargins(10, 5, 10, 5)
# 状态指示灯
indicator = QLabel()
indicator.setFixedSize(20, 20)
indicator.setStyleSheet("""
QLabel {
background-color: #9E9E9E;
border-radius: 10px;
border: 2px solid #555555;
}
""")
# 状态名称标签
nameLabel = QLabel(info["name"])
2025-09-11 20:42:12 +08:00
nameLabel.setFixedWidth(100) # 加宽名称标签(与左侧一致)
nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
2025-09-10 18:07:58 +08:00
nameLabel.setStyleSheet("font-size: 14px; color: #FFFFFF;")
nameLabel.setFont(QFont("Microsoft YaHei", 12))
# 状态值标签
valueLabel = QLabel(info["value"])
valueLabel.setStyleSheet("""
QLabel {
font-size: 16px;
2025-09-10 11:20:31 +08:00
font-weight: bold;
2025-09-10 18:07:58 +08:00
color: #FFFFFF;
2025-09-11 20:42:12 +08:00
background-color: #2D2D2D;
border: none;
padding: 0px;
2025-09-10 11:20:31 +08:00
}
""")
valueLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
2025-09-11 20:42:12 +08:00
valueLabel.setMinimumWidth(150) # 加宽值标签(与左侧一致)
2025-09-10 11:20:31 +08:00
itemLayout.addWidget(indicator)
itemLayout.addSpacing(10)
itemLayout.addWidget(nameLabel)
itemLayout.addStretch()
itemLayout.addWidget(valueLabel)
self.statusWidgets.append({
'indicator': indicator,
'nameLabel': nameLabel,
'valueLabel': valueLabel,
2025-09-10 18:07:58 +08:00
'status': False,
'initial_value': info["value"]
2025-09-10 11:20:31 +08:00
})
2025-09-10 18:07:58 +08:00
rightLayout.addWidget(statusItem)
2025-09-10 11:20:31 +08:00
statusLayout.addWidget(leftGroup)
2025-09-11 20:42:12 +08:00
statusLayout.addStretch(0) # 减小中间空白比例原1
2025-09-10 11:20:31 +08:00
statusLayout.addWidget(rightGroup)
parent_layout.addWidget(statusWidget)
def _init_operation_buttons(self, parent_layout):
2025-09-10 18:07:58 +08:00
"""初始化操作按钮(下料完成/生产异常/生产取消)"""
2025-09-10 11:20:31 +08:00
buttonContainer = QWidget()
buttonLayout = QHBoxLayout(buttonContainer)
buttonLayout.setContentsMargins(0, 20, 0, 0)
buttonLayout.setSpacing(30)
2025-09-10 18:07:58 +08:00
# 按钮图标(需替换为实际图标路径)
down_icon_path = "img.png"
error_icon_path = "img.png"
cancel_icon_path = "img.png"
self.startButton = QPushButton("下料完成")
self.restartButton = QPushButton("生产异常")
self.stopButton = QPushButton("生产取消")
# 设置按钮图标
self.startButton.setIcon(QIcon(down_icon_path))
self.restartButton.setIcon(QIcon(error_icon_path))
self.stopButton.setIcon(QIcon(cancel_icon_path))
# 设置图标大小
self.startButton.setIconSize(QSize(20, 20))
self.restartButton.setIconSize(QSize(20, 20))
self.stopButton.setIconSize(QSize(20, 20))
2025-09-10 11:20:31 +08:00
button_base_style = """
QPushButton {
font-size: 16px;
font-weight: bold;
padding: 10px 20px;
2025-09-10 18:07:58 +08:00
border-radius: 15px;
border: 1px solid;
2025-09-10 11:20:31 +08:00
min-width: 100px;
}
QPushButton:hover {
opacity: 0.9;
}
QPushButton:pressed {
opacity: 0.8;
}
"""
self.startButton.setStyleSheet(button_base_style + """
QPushButton {
2025-09-10 18:07:58 +08:00
background-color: #00796B;
2025-09-10 11:20:31 +08:00
color: white;
2025-09-10 18:07:58 +08:00
border-color: #004D40;
2025-09-10 11:20:31 +08:00
}
""")
self.restartButton.setStyleSheet(button_base_style + """
QPushButton {
2025-09-10 18:07:58 +08:00
background-color: #E65100;
2025-09-10 11:20:31 +08:00
color: white;
2025-09-10 18:07:58 +08:00
border-color: #BF360C;
2025-09-10 11:20:31 +08:00
}
""")
self.stopButton.setStyleSheet(button_base_style + """
QPushButton {
2025-09-10 18:07:58 +08:00
background-color: #C62828;
2025-09-10 11:20:31 +08:00
color: white;
2025-09-10 18:07:58 +08:00
border-color: #8E0000;
2025-09-10 11:20:31 +08:00
}
""")
button_font = QFont("Microsoft YaHei", 12, QFont.Bold)
self.startButton.setFont(button_font)
self.restartButton.setFont(button_font)
self.stopButton.setFont(button_font)
self.startButton.clicked.connect(self.on_start_clicked)
self.restartButton.clicked.connect(self.on_restart_clicked)
self.stopButton.clicked.connect(self.on_stop_clicked)
buttonLayout.addStretch(1)
buttonLayout.addWidget(self.startButton)
buttonLayout.addWidget(self.restartButton)
buttonLayout.addWidget(self.stopButton)
buttonLayout.addStretch(1)
parent_layout.addWidget(buttonContainer)
def _init_timers(self):
"""初始化定时器(时间更新+状态模拟)"""
# 时间更新定时器(每秒更新一次)
self.time_timer = QTimer()
self.time_timer.timeout.connect(self.update_time)
self.time_timer.start(1000)
# 状态模拟定时器每3秒更新一次
self.status_timer = QTimer()
self.status_timer.timeout.connect(self.simulate_mcu_query)
self.status_timer.start(3000)
def get_current_time(self):
"""获取格式化的当前时间"""
2025-09-10 18:07:58 +08:00
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2025-09-10 11:20:31 +08:00
def update_time(self):
2025-09-10 18:07:58 +08:00
"""更新时间显示并触发重绘"""
self.current_datetime = self.get_current_time()
self.update() # 触发paintEvent重绘
def paintEvent(self, event):
"""重写绘画事件,在右上角绘制日期时间文本"""
super().paintEvent(event) # 调用父类方法保持原有绘制
# 创建QPainter对象
painter = QPainter(self)
painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) # 文本抗锯齿
# 设置字体
font = QFont("Arial", 12, QFont.Bold)
painter.setFont(font)
# 设置文本颜色
painter.setPen(QColor("#00FF9D"))
# 计算文本位置(右上角,留出边距)
text = f"🕒 {self.current_datetime}"
text_rect = painter.boundingRect(self.rect(), Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop, text)
x = self.width() - text_rect.width() - 15 # 右边距15px
y = 15 # 上边距15px
# 绘制文本
painter.drawText(x, y + text_rect.height(), text)
2025-09-10 11:20:31 +08:00
def simulate_mcu_query(self):
"""模拟单片机状态查询"""
import random # 仅用于模拟,实际项目替换为真实通信逻辑
if self.is_running:
for widget in self.statusWidgets:
status = random.choice([True, False])
widget['status'] = status
if status:
2025-09-11 20:42:12 +08:00
# 状态为"是"时的样式 - 去除边框
2025-09-10 11:20:31 +08:00
widget['valueLabel'].setText("")
widget['valueLabel'].setStyleSheet("""
QLabel {
font-size: 18px;
font-weight: bold;
2025-09-10 18:07:58 +08:00
color: #00E676;
2025-09-11 20:42:12 +08:00
background-color: #2D2D2D; /* 与父容器相同背景色 */
2025-09-10 11:20:31 +08:00
padding: 5px 10px;
2025-09-11 20:42:12 +08:00
border: none; /* 明确去除边框 */
2025-09-10 11:20:31 +08:00
min-width: 60px;
}
""")
widget['indicator'].setStyleSheet("""
QLabel {
2025-09-10 18:07:58 +08:00
background-color: #00E676;
2025-09-10 11:20:31 +08:00
border-radius: 10px;
2025-09-10 18:07:58 +08:00
border: 2px solid #00796B;
2025-09-10 11:20:31 +08:00
}
""")
else:
2025-09-11 20:42:12 +08:00
# 状态为"否"时的样式 - 去除边框
2025-09-10 11:20:31 +08:00
widget['valueLabel'].setText("")
widget['valueLabel'].setStyleSheet("""
QLabel {
font-size: 18px;
font-weight: bold;
2025-09-10 18:07:58 +08:00
color: #FF5252;
2025-09-11 20:42:12 +08:00
background-color: #2D2D2D; /* 与父容器相同背景色 */
2025-09-10 11:20:31 +08:00
padding: 5px 10px;
2025-09-11 20:42:12 +08:00
border: none; /* 明确去除边框 */
2025-09-10 11:20:31 +08:00
min-width: 60px;
}
""")
widget['indicator'].setStyleSheet("""
QLabel {
2025-09-10 18:07:58 +08:00
background-color: #FF5252;
2025-09-10 11:20:31 +08:00
border-radius: 10px;
2025-09-10 18:07:58 +08:00
border: 2px solid #C62828;
2025-09-10 11:20:31 +08:00
}
""")
def on_start_clicked(self):
"""开始按钮点击事件"""
if not self.is_running:
self.is_running = True
print("系统已启动,开始监控状态...")
self.simulate_mcu_query() # 启动时立即更新一次状态
def on_stop_clicked(self):
"""停止按钮点击事件"""
if self.is_running:
self.is_running = False
print("系统已停止,状态监控暂停...")
def on_restart_clicked(self):
"""重启按钮点击事件"""
print("系统正在重启...")
self.is_running = False
2025-09-11 20:42:12 +08:00
# 重置所有状态为初始值和样式
for i, widget in enumerate(self.statusWidgets):
2025-09-10 11:20:31 +08:00
widget['status'] = False
2025-09-11 20:42:12 +08:00
# 恢复初始值
widget['valueLabel'].setText(widget['initial_value'])
# 恢复初始样式(无边框)
2025-09-10 11:20:31 +08:00
widget['valueLabel'].setStyleSheet("""
QLabel {
2025-09-11 20:42:12 +08:00
font-size: 16px;
2025-09-10 11:20:31 +08:00
font-weight: bold;
2025-09-11 20:42:12 +08:00
color: #FFFFFF;
background-color: #2D2D2D;
border: none;
padding: 0px;
min-width: 80px;
2025-09-10 11:20:31 +08:00
}
""")
widget['indicator'].setStyleSheet("""
QLabel {
2025-09-11 20:42:12 +08:00
background-color: #9E9E9E;
2025-09-10 11:20:31 +08:00
border-radius: 10px;
2025-09-11 20:42:12 +08:00
border: 2px solid #555555;
2025-09-10 11:20:31 +08:00
}
""")
# 重启后自动开始
QTimer.singleShot(1000, self.on_start_clicked)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = StatusMonitor()
window.show()
sys.exit(app.exec())