jiateng_ws/widgets/main_window.py

292 lines
12 KiB
Python
Raw Normal View History

2025-06-07 10:45:09 +08:00
import os
import sys
import logging
import json
2025-06-07 10:45:09 +08:00
from datetime import datetime
# 导入PySide6
from PySide6.QtWidgets import QWidget, QMessageBox, QTableWidgetItem, QStackedWidget, QLabel
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QBrush, QColor
# 导入UI
from ui.main_window_ui import MainWindowUI
# 导入相机显示组件和设置组件
from widgets.camera_display_widget import CameraDisplayWidget
from widgets.camera_settings_widget import CameraSettingsWidget
# 导入检验配置管理器
from utils.inspection_config_manager import InspectionConfigManager
2025-06-07 10:45:09 +08:00
class MainWindow(MainWindowUI):
"""主窗口"""
def __init__(self, user_id=None, user_name=None, corp_name=None, corp_id=None, position_id=None):
super().__init__()
self.user_id = user_id
self.user_name = user_name
self.corp_name = corp_name
self.corp_id = corp_id
self.position_id = position_id
# 设置窗口标题
if user_name and corp_name:
self.setWindowTitle(f"腾智微丝产线包装系统 - {user_name} ({corp_name})")
# 加载配置文件
self.config = self.load_config()
self.camera_enabled = self.config.get('camera', {}).get('enabled', False)
# 初始化检验配置管理器
self.inspection_manager = InspectionConfigManager.get_instance()
# 只有在相机启用时创建相机显示组件
if self.camera_enabled:
# 创建相机显示组件并添加到上料区
self.camera_display = CameraDisplayWidget()
self.material_content_layout.addWidget(self.camera_display)
else:
# 在上料区添加占位标签
self.material_placeholder = QLabel("相机功能已禁用")
self.material_placeholder.setAlignment(Qt.AlignCenter)
self.material_placeholder.setStyleSheet("color: #888888; background-color: #f0f0f0;")
self.material_content_layout.addWidget(self.material_placeholder)
2025-06-07 10:45:09 +08:00
# 为下料区添加占位标签,确保它保持为空
self.output_placeholder = QLabel("下料区 - 暂无内容")
self.output_placeholder.setAlignment(Qt.AlignCenter)
self.output_placeholder.setStyleSheet("color: #888888; background-color: #f0f0f0;")
self.output_content_layout.addWidget(self.output_placeholder)
# 创建堆叠部件
self.stacked_widget = QStackedWidget()
self.stacked_widget.addWidget(self.central_widget) # 主页面
# 不在这里直接初始化相机设置组件
# 延迟创建保证创建的时候SettingsUI的所有控件都已经准备好
self.camera_settings = None
# 设置中央部件为堆叠部件
self.setCentralWidget(self.stacked_widget)
# 连接信号和槽
self.connect_signals()
2025-06-07 10:45:09 +08:00
# 默认显示主页面
self.stacked_widget.setCurrentIndex(0)
# 初始化数据
self.initialize_data()
# 配置检验列 - 使用检验配置管理器获取启用的列数和标题
self.update_inspection_columns()
2025-06-07 10:45:09 +08:00
logging.info(f"主窗口已创建,用户: {user_name}")
def load_config(self):
"""加载配置文件"""
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "app_config.json")
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
logging.info(f"已加载配置文件: {config_path}")
return config
except Exception as e:
logging.error(f"加载配置文件失败: {e}")
return {}
2025-06-07 10:45:09 +08:00
def connect_signals(self):
# 连接菜单动作
self.main_action.triggered.connect(self.show_main_page)
self.settings_action.triggered.connect(self.show_settings_page)
# 工程号输入框回车事件
self.order_edit.returnPressed.connect(self.handle_order_enter)
2025-06-07 10:45:09 +08:00
# 连接按钮事件
self.input_button.clicked.connect(self.handle_input)
self.output_button.clicked.connect(self.handle_output)
self.start_button.clicked.connect(self.handle_start)
self.stop_button.clicked.connect(self.handle_stop)
# 只有在相机启用时连接相机信号
if self.camera_enabled and hasattr(self, 'camera_display'):
self.camera_display.signal_camera_status.connect(self.handle_camera_status)
2025-06-07 10:45:09 +08:00
def initialize_data(self):
"""初始化界面数据"""
# 设置订单和批号
self.order_edit.setText("ORD-2025-001")
self.tray_edit.setCurrentText("托盘1")
2025-06-07 10:45:09 +08:00
# 初始化项目表格数据示例
project_data = [
["100", "50", "200", "95%"],
["3000", "1500", "6000", "92%"],
["36000", "18000", "72000", "90%"],
["120000", "60000", "240000", "91%"]
]
for row in range(4):
for col in range(0, 4): # 从第2列开始跳过项目列
item = QTableWidgetItem(project_data[row][col])
2025-06-07 10:45:09 +08:00
# item.setTextAlignment(Qt.AlignCenter) # 设置文本居中对齐
self.project_table.setItem(row, col, item)
# 初始化任务表格数据示例 - 注意现在表格有3行第0行是一级标题第1行是二级标题第2行是数据行
# 数据应该填充在第2行索引为2
data = ["200", "95", "0", "0"] # 分别对应:总生产数量、总生产公斤、已完成数量、已完成公斤
for col, value in enumerate(data):
item = QTableWidgetItem(value)
item.setTextAlignment(Qt.AlignCenter) # 设置文本居中对齐
self.task_table.setItem(2, col, item)
def update_inspection_columns(self):
"""更新检验列配置 - 使用检验配置管理器获取启用的列数和标题"""
try:
# 获取已启用的检验配置
enabled_configs = self.inspection_manager.get_enabled_configs()
# 获取启用的列数
column_count = len(enabled_configs)
if column_count == 0:
# 如果没有启用的列,至少显示一列
column_count = 1
headers = ["检验项"]
else:
# 如果有启用的列,使用配置的标题
headers = [config['display_name'] for config in enabled_configs]
# 设置检验列
self.set_inspection_columns(column_count, headers)
logging.info(f"已更新检验列配置:{column_count}列, 标题: {headers}")
except Exception as e:
logging.error(f"更新检验列配置失败: {str(e)}")
# 如果更新失败,使用默认配置
self.set_inspection_columns(1, ["检验项"])
2025-06-07 10:45:09 +08:00
def show_main_page(self):
self.stacked_widget.setCurrentWidget(self.central_widget)
# 更新检验列配置
self.update_inspection_columns()
# 只有在相机启用时处理相机显示
if self.camera_enabled and hasattr(self, 'camera_display'):
# 如果相机已连接,直接开始显示相机画面
if self.camera_display.camera_manager.isOpen:
if not self.camera_display.camera_manager.isGrabbing:
self.camera_display.start_display()
2025-06-07 10:45:09 +08:00
logging.info("显示主页面")
def show_settings_page(self):
"""显示设置页面"""
# 延迟创建设置组件
if not hasattr(self, 'settings_widget'):
from widgets.settings_widget import SettingsWidget
self.settings_widget = SettingsWidget(self)
self.stacked_widget.addWidget(self.settings_widget)
# 切换到设置页面
self.stacked_widget.setCurrentWidget(self.settings_widget)
2025-06-07 10:45:09 +08:00
logging.info("显示设置页面")
def handle_input(self):
"""处理上料按钮点击事件"""
logging.info("上料按钮被点击")
QMessageBox.information(self, "操作提示", "开始上料操作")
# 这里添加上料相关的业务逻辑
def handle_output(self):
"""处理下料按钮点击事件"""
logging.info("下料按钮被点击")
QMessageBox.information(self, "操作提示", "开始下料操作")
# 这里添加下料相关的业务逻辑
def handle_start(self):
"""处理开始按钮点击事件"""
logging.info("开始按钮被点击")
# 只有在相机启用时处理相机显示
if self.camera_enabled and hasattr(self, 'camera_display'):
# 开始显示相机画面
if self.camera_display.camera_manager.isOpen:
self.camera_display.start_display()
2025-06-07 10:45:09 +08:00
QMessageBox.information(self, "操作提示", "生产线已启动")
# 这里添加启动生产线的业务逻辑
def handle_stop(self):
"""处理暂停按钮点击事件"""
logging.info("暂停按钮被点击")
# 只有在相机启用时处理相机显示
if self.camera_enabled and hasattr(self, 'camera_display'):
# 停止显示相机画面
self.camera_display.stop_display()
2025-06-07 10:45:09 +08:00
QMessageBox.information(self, "操作提示", "生产线已暂停")
# 这里添加暂停生产线的业务逻辑
def handle_camera_status(self, is_connected, message):
"""处理相机状态变化"""
if is_connected:
logging.info("相机已连接并显示")
else:
logging.warning(f"相机显示问题: {message}")
def handle_camera_connection(self, is_connected, message):
"""处理相机连接状态变化"""
if is_connected:
logging.info("相机已连接")
# 如果当前在主页面,直接开始显示相机画面
if self.stacked_widget.currentWidget() == self.central_widget:
self.camera_display.start_display()
else:
if message:
logging.warning(f"相机连接失败: {message}")
else:
logging.info("相机已断开")
# 如果相机断开,确保停止显示
self.camera_display.stop_display()
def handle_camera_params_changed(self, exposure_time, gain, frame_rate):
"""处理相机参数变化"""
logging.info(f"相机参数已更新: 曝光={exposure_time:.1f}μs, 增益={gain:.1f}dB, 帧率={frame_rate:.1f}fps")
# 这里可以添加对相机参数变化的处理逻辑
def handle_camera_error(self, error_msg):
"""处理相机错误"""
logging.error(f"相机错误: {error_msg}")
QMessageBox.warning(self, "相机错误", error_msg)
def closeEvent(self, event):
"""窗口关闭事件"""
# 只有在相机启用时处理相机关闭
if self.camera_enabled and hasattr(self, 'camera_display'):
# 停止相机显示
self.camera_display.stop_display()
2025-06-07 10:45:09 +08:00
# 接受关闭事件
event.accept()
def handle_order_enter(self):
"""处理工程号输入框按下回车事件"""
logging.info("工程号输入框按下回车事件")
# 获取当前输入的工程号
order_text = self.order_edit.text().strip()
if order_text:
logging.info(f"输入的工程号: {order_text}")
QMessageBox.information(self, "工程号确认", f"您输入的工程号是: {order_text}")
# 这里可以添加其他工程号处理逻辑
else:
logging.warning("工程号为空")
QMessageBox.warning(self, "输入提示", "请输入有效的工程号")
# 处理完后可以清除焦点,让输入框失去焦点
self.central_widget.setFocus()