import os import sys import logging import json 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 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) # 为下料区添加占位标签,确保它保持为空 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() # 默认显示主页面 self.stacked_widget.setCurrentIndex(0) # 初始化数据 self.initialize_data() # 配置检验列 - 使用检验配置管理器获取启用的列数和标题 self.update_inspection_columns() 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 {} 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) # 连接按钮事件 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) def initialize_data(self): """初始化界面数据""" # 设置订单和批号 self.order_edit.setText("ORD-2025-001") self.tray_edit.setCurrentText("托盘1") # 初始化项目表格数据示例 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]) # 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, ["检验项"]) 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() 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) 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() QMessageBox.information(self, "操作提示", "生产线已启动") # 这里添加启动生产线的业务逻辑 def handle_stop(self): """处理暂停按钮点击事件""" logging.info("暂停按钮被点击") # 只有在相机启用时处理相机显示 if self.camera_enabled and hasattr(self, 'camera_display'): # 停止显示相机画面 self.camera_display.stop_display() 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() # 接受关闭事件 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()