diff --git a/db/jtDB.db b/db/jtDB.db index 4433962..388d6a8 100644 Binary files a/db/jtDB.db and b/db/jtDB.db differ diff --git a/from pymodbus.py b/from pymodbus.py index 73bf610..ddfea1b 100644 --- a/from pymodbus.py +++ b/from pymodbus.py @@ -2,7 +2,7 @@ from pymodbus.client import ModbusTcpClient import time client = ModbusTcpClient('localhost', port=5020) client.connect() -client.write_registers(address=11, values=[21962]) +client.write_registers(address=11, values=[9562]) # client.write_registers(address=3, values=[0]) # time.sleep(2) # client.write_registers(address=0, values=[0]) diff --git a/widgets/main_window.py b/widgets/main_window.py index f97a925..e05d8ad 100644 --- a/widgets/main_window.py +++ b/widgets/main_window.py @@ -59,6 +59,12 @@ class MainWindow(MainWindowUI): emergency_stop_signal = Signal(int, str) # 用于在主线程中处理急停信号 diameter_warning_signal = Signal(float, str, str) # 参数:final_value, bccd, tccd + # 新增的线径警告弹框信号 - 参数:值, 最小值, 最大值 + diameter_alert_signal = Signal(float, float, float) + + # 新增的重量警告弹框信号 - 参数:值, 最小值, 最大值 + weight_alert_signal = Signal(float, float, float) + def __init__(self, user_id=None, user_name=None, corp_name=None, corp_id=None): """初始化主窗口""" super().__init__(user_id) @@ -335,6 +341,12 @@ class MainWindow(MainWindowUI): if hasattr(self, 'luno_query_button'): self.luno_query_button.clicked.connect(self.handle_luno_query) + # 连接新的线径警告弹框信号 + self.diameter_alert_signal.connect(self.show_diameter_alert) + + # 连接重量警告弹框信号 + self.weight_alert_signal.connect(self.show_weight_alert) + def update_inspection_columns(self): """更新检验列配置 - 使用检验配置管理器获取启用的列数和标题""" try: @@ -866,17 +878,7 @@ class MainWindow(MainWindowUI): self.serial_manager.stop_keyboard_listener() self.serial_manager.close_all_ports() - def clear_operation_status(self, operation_type): - """清除右上角的操作状态显示。""" - status_label_name = f"{operation_type}_status_label" - if hasattr(self, status_label_name): - try: - getattr(self, status_label_name).deleteLater() - delattr(self, status_label_name) - logging.info(f"已清除 '{operation_type}' 状态标签。") - except AttributeError: - pass # Failsafe - + def handle_camera_status(self, is_connected, message): """相机状态处理的空方法,保留是为了兼容性""" pass @@ -2437,48 +2439,23 @@ class MainWindow(MainWindowUI): # 检查称重值是否在范围内 if net_weight_kg < min_weight or net_weight_kg > max_weight: # 写入寄存器D10 给值 2 表示重量超出范围 - modbus = ModbusUtils() - client = modbus.get_client() - modbus.write_register_until_success(client, 10, 2) - modbus.close_client(client) - # 显示自动关闭的警告提示框 - self.warning_msg = QMessageBox(self) - self.warning_msg.setIcon(QMessageBox.Warning) - self.warning_msg.setWindowTitle('重量超出范围') - self.warning_msg.setText(f"称重值 {net_weight_kg:.2f}kg 不在轴重要求范围内 ({min_weight:.1f} - {max_weight:.1f}kg)") - self.warning_msg.setStandardButtons(QMessageBox.Ok) # 添加确定按钮 - self.warning_msg.setModal(False) # 确保非模态 - self.warning_msg.setWindowFlags(self.warning_msg.windowFlags() | Qt.WindowStaysOnTopHint) # 置顶显示 + try: + modbus = ModbusUtils() + client = modbus.get_client() + modbus.write_register_until_success(client, 10, 2) + modbus.close_client(client) + except Exception as e: + logging.error(f"写入Modbus寄存器失败: {str(e)}") - # 连接按钮点击信号 - self.warning_msg.buttonClicked.connect(lambda btn: self.warning_msg.close()) - - # 使用 show 而非 exec_ 保持非阻塞 - self.warning_msg.show() - - # 强制关闭方法1:使用多种定时器策略 - def force_close_weight_warning(): - try: - if hasattr(self, 'warning_msg') and self.warning_msg: - if self.warning_msg.isVisible(): - self.warning_msg.close() - self.warning_msg.deleteLater() - logging.debug("重量警告弹框已强制关闭") - else: - logging.debug("重量警告弹框已不可见,跳过关闭") - except Exception as e: - logging.warning(f"强制关闭重量警告弹框时出错: {str(e)}") - finally: - # 清理引用 - if hasattr(self, 'warning_msg'): - delattr(self, 'warning_msg') - - # 使用多个定时器确保关闭 - QTimer.singleShot(5000, force_close_weight_warning) # 5秒后关闭 - QTimer.singleShot(6000, force_close_weight_warning) # 6秒后再次尝试 + # 使用信号触发弹框显示 - 避免主线程阻塞 + logging.warning(f"称重值 {net_weight_kg:.2f}kg 超出轴重要求范围 ({min_weight:.1f} - {max_weight:.1f}kg),发送信号显示警告") + try: + self.weight_alert_signal.emit(net_weight_kg, min_weight, max_weight) + except Exception as e: + logging.error(f"发送重量警告信号失败: {str(e)}", exc_info=True) # 阻止继续执行,等待用户处理 - logging.warning(f"称重值 {weight_kg:.3f}kg 超出轴重要求范围,已阻止保存,等待用户处理") + logging.warning(f"称重值 {weight_kg:.3f}kg 超出轴重要求范围,已阻止保存") return else: logging.info(f"称重值 {weight_kg:.3f}kg 在轴重要求范围内 ({min_weight:.1f} - {max_weight:.1f}kg)") @@ -3030,8 +3007,6 @@ class MainWindow(MainWindowUI): if self._loading_info and self._current_stow_num > 0: self.show_operation_status("拆垛层数", "input", str(self._current_stow_num)) else: - # 上料任务完成,清除状态显示 - self.clear_operation_status("input") # 上料任务完成,恢复上料按钮样式 self.restore_input_button_style() logging.info("上料任务完成,恢复上料按钮样式") @@ -3551,52 +3526,20 @@ class MainWindow(MainWindowUI): # 检查线径值是否在范围内 if final_value < min_diameter or final_value > max_diameter: - # 写入寄存器D10 给值 3 表示线径超出范围 - modbus = ModbusUtils() - modbus_client = modbus.get_client() - modbus.write_register_until_success(modbus_client, 10, 3) - - # 显示自动关闭的警告提示框 - self.diameter_warning_msg = QMessageBox(self) - self.diameter_warning_msg.setIcon(QMessageBox.Warning) - self.diameter_warning_msg.setWindowTitle('线径超出范围') - self.diameter_warning_msg.setText(f"线径值 {final_value:.3f}mm 不在线径公差范围内 ({min_diameter:.3f} - {max_diameter:.3f}mm)") - self.diameter_warning_msg.setStandardButtons(QMessageBox.Ok) # 添加确定按钮 - self.diameter_warning_msg.setModal(False) # 确保非模态 - self.diameter_warning_msg.setWindowFlags(self.diameter_warning_msg.windowFlags() | Qt.WindowStaysOnTopHint) # 置顶显示 - - # 连接按钮点击信号 - self.diameter_warning_msg.buttonClicked.connect(lambda btn: self.diameter_warning_msg.close()) - # 使用 show 而非 exec_ 保持非阻塞 - self.diameter_warning_msg.show() - # 强制关闭方法:使用多种定时器策略 - def force_close_diameter_warning(): - try: - if hasattr(self, 'diameter_warning_msg') and self.diameter_warning_msg: - if self.diameter_warning_msg.isVisible(): - self.diameter_warning_msg.close() - self.diameter_warning_msg.deleteLater() - logging.debug("线径警告弹框已强制关闭") - else: - logging.debug("线径警告弹框已不可见,跳过关闭") - except Exception as e: - logging.warning(f"强制关闭线径警告弹框时出错: {str(e)}") - finally: - # 清理引用 - if hasattr(self, 'diameter_warning_msg'): - delattr(self, 'diameter_warning_msg') - - # 使用多个定时器确保关闭 - QTimer.singleShot(2000, force_close_diameter_warning) # 2秒后关闭 - QTimer.singleShot(3000, force_close_diameter_warning) # 3秒后再次尝试 + # 使用信号触发弹框显示 - 避免主线程阻塞 + logging.warning(f"线径值 {final_value:.3f}mm 超出线径公差范围 ({min_diameter:.3f} - {max_diameter:.3f}mm),发送信号显示警告") + try: + self.diameter_alert_signal.emit(final_value, min_diameter, max_diameter) + except Exception as e: + logging.error(f"发送线径警告信号失败: {str(e)}", exc_info=True) # 重置测量列表,防止重复触发 self._diameter_measurements = [] # 阻止继续执行,等待用户处理 - logging.warning(f"线径值 {final_value:.3f}mm 超出线径公差范围,已阻止保存,等待用户处理") + logging.warning(f"线径值 {final_value:.3f}mm 超出线径公差范围,已阻止保存") return else: logging.info(f"线径值 {final_value:.3f}mm 在线径公差范围内 ({min_diameter:.3f} - {max_diameter:.3f}mm)") @@ -3678,56 +3621,11 @@ class MainWindow(MainWindowUI): @Slot(float, str, str) def show_diameter_warning(self, final_value, bccd, tccd): - """显示线径超出范围警告(在主线程中执行)""" - try: - # 显示自动关闭的警告提示框 - self.diameter_warning_msg = QMessageBox(self) - self.diameter_warning_msg.setIcon(QMessageBox.Warning) - self.diameter_warning_msg.setWindowTitle('线径超出范围') - self.diameter_warning_msg.setText(f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd})") - self.diameter_warning_msg.setStandardButtons(QMessageBox.Ok) # 添加确定按钮 - self.diameter_warning_msg.setModal(False) # 确保非模态 - self.diameter_warning_msg.setWindowFlags(self.diameter_warning_msg.windowFlags() | Qt.WindowStaysOnTopHint) # 置顶显示 - - # 连接按钮点击信号 - self.diameter_warning_msg.buttonClicked.connect(lambda btn: self.diameter_warning_msg.close()) - - # 显示提示框(非模态) - self.diameter_warning_msg.show() - - # Windows平台强制关闭方法 - def force_close_diameter_warning(): - try: - if hasattr(self, 'diameter_warning_msg') and self.diameter_warning_msg: - if self.diameter_warning_msg.isVisible(): - # 方法1:正常关闭 - self.diameter_warning_msg.close() - # 方法2:强制删除 - self.diameter_warning_msg.deleteLater() - # 方法3:隐藏窗口 - self.diameter_warning_msg.hide() - # 方法4:设置为不可见 - self.diameter_warning_msg.setVisible(False) - logging.debug("线径警告弹框已强制关闭") - else: - logging.debug("线径警告弹框已不可见,跳过关闭") - except Exception as e: - logging.warning(f"强制关闭线径警告弹框时出错: {str(e)}") - finally: - # 清理引用 - try: - if hasattr(self, 'diameter_warning_msg'): - delattr(self, 'diameter_warning_msg') - except: - pass - - # 使用多个定时器确保关闭(Windows平台优化) - QTimer.singleShot(2000, force_close_diameter_warning) # 1秒后关闭 - QTimer.singleShot(3000, force_close_diameter_warning) # 2秒后最后尝试 - - logging.info(f"线径警告弹框已显示,将在1-3秒后自动关闭") - except Exception as e: - logging.error(f"显示线径警告弹框时出错: {str(e)}") + """显示线径超出范围警告(在主线程中执行)- 为避免冲突,此方法已弃用,仅保留接口""" + # 这个方法已经被新的线径处理逻辑取代,为避免冲突,此处不再显示弹框 + # 仅记录日志,保持接口兼容性 + logging.info(f"线径警告信号已接收,但弹框显示已被新逻辑取代: 线径值 {final_value:.3f}mm, 范围 {bccd} - {tccd}") + return def on_scanner_data_received(self, port_name, data): """扫码器数据接收回调函数 @@ -5111,6 +5009,154 @@ class MainWindow(MainWindowUI): logging.warning(f"线径数据处理超时,强制释放锁。处理时间: {processing_time:.2f}秒") self._processing_diameter_lock = False + @Slot(float, float, float) + def show_diameter_alert(self, value, min_value, max_value): + """显示线径超出范围警告 - 通过信号触发,使用exec_强制显示""" + try: + # 使用更强制的方式显示警告对话框 + from PySide6.QtWidgets import QApplication + + # 记录当前时间,用于跟踪弹框显示时间 + start_time = time.time() + logging.info(f"开始创建线径警告弹框,时间: {start_time}") + + # 创建一个模态对话框 - 使用exec_方式显示 + msg = QMessageBox() + msg.setIcon(QMessageBox.Critical) # 使用Critical图标更明显 + msg.setWindowTitle('警告:线径超出范围!') + msg.setText(f"线径值 {value:.3f}mm 超出范围!

允许范围: {min_value:.3f} - {max_value:.3f}mm") + msg.setStandardButtons(QMessageBox.Ok) + + # 设置样式,使其更显眼 + msg.setStyleSheet(""" + QMessageBox { + background-color: #ffeeee; + border: 3px solid #ff0000; + font-size: 14px; + } + QLabel { + color: #ff0000; + font-size: 16px; + font-weight: bold; + min-width: 250px; + min-height: 80px; + } + QPushButton { + background-color: #ff6666; + color: white; + font-weight: bold; + min-width: 80px; + min-height: 30px; + } + """) + + # 确保对话框显示在所有窗口之上 + msg.setWindowFlags(Qt.WindowStaysOnTopHint) + + # 强制处理事件,确保UI更新 + QApplication.processEvents() + + # 使用定时器在2秒后自动点击确定按钮 + def auto_close(): + try: + # 查找确定按钮并点击 + for button in msg.buttons(): + if msg.buttonRole(button) == QMessageBox.AcceptRole: + button.click() + logging.info(f"已自动点击确定按钮,弹框显示时长: {time.time() - start_time:.2f}秒") + return + # 如果没有找到确定按钮,直接关闭 + msg.done(QMessageBox.Ok) + logging.info(f"已自动关闭弹框,弹框显示时长: {time.time() - start_time:.2f}秒") + except Exception as e: + logging.error(f"自动关闭弹框失败: {str(e)}") + + # 设置自动关闭定时器 + QTimer.singleShot(2000, auto_close) + + # 显示弹框并阻塞直到用户关闭或自动关闭 + logging.info(f"即将显示线径警告弹框...") + msg.exec_() # 使用exec_而不是show,确保弹框显示 + + # 记录日志 + logging.info(f"线径警告弹框已关闭,总显示时长: {time.time() - start_time:.2f}秒") + except Exception as e: + logging.error(f"显示线径警告弹框失败: {str(e)}", exc_info=True) + + @Slot(float, float, float) + def show_weight_alert(self, value, min_value, max_value): + """显示重量超出范围警告 - 通过信号触发,使用exec_强制显示""" + try: + # 使用更强制的方式显示警告对话框 + from PySide6.QtWidgets import QApplication + + # 记录当前时间,用于跟踪弹框显示时间 + start_time = time.time() + logging.info(f"开始创建重量警告弹框,时间: {start_time}") + + # 创建一个模态对话框 - 使用exec_方式显示 + msg = QMessageBox() + msg.setIcon(QMessageBox.Critical) # 使用Critical图标更明显 + msg.setWindowTitle('警告:重量超出范围!') + msg.setText(f"称重值 {value:.2f}kg 超出范围!

允许范围: {min_value:.1f} - {max_value:.1f}kg") + msg.setStandardButtons(QMessageBox.Ok) + + # 设置样式,使其更显眼 + msg.setStyleSheet(""" + QMessageBox { + background-color: #ffeeee; + border: 3px solid #ff0000; + font-size: 14px; + } + QLabel { + color: #ff0000; + font-size: 16px; + font-weight: bold; + min-width: 250px; + min-height: 80px; + } + QPushButton { + background-color: #ff6666; + color: white; + font-weight: bold; + min-width: 80px; + min-height: 30px; + } + """) + + # 确保对话框显示在所有窗口之上 + msg.setWindowFlags(Qt.WindowStaysOnTopHint) + + # 强制处理事件,确保UI更新 + QApplication.processEvents() + + # 使用定时器在2秒后自动点击确定按钮 + def auto_close(): + try: + # 查找确定按钮并点击 + for button in msg.buttons(): + if msg.buttonRole(button) == QMessageBox.AcceptRole: + button.click() + logging.info(f"已自动点击确定按钮,弹框显示时长: {time.time() - start_time:.2f}秒") + return + # 如果没有找到确定按钮,直接关闭 + msg.done(QMessageBox.Ok) + logging.info(f"已自动关闭弹框,弹框显示时长: {time.time() - start_time:.2f}秒") + except Exception as e: + logging.error(f"自动关闭弹框失败: {str(e)}") + + # 设置自动关闭定时器 + QTimer.singleShot(2000, auto_close) + + # 显示弹框并阻塞直到用户关闭或自动关闭 + logging.info(f"即将显示重量警告弹框...") + msg.exec_() # 使用exec_而不是show,确保弹框显示 + + # 记录日志 + logging.info(f"重量警告弹框已关闭,总显示时长: {time.time() - start_time:.2f}秒") + except Exception as e: + logging.error(f"显示重量警告弹框失败: {str(e)}", exc_info=True) + def safe_str(val):