diff --git a/camera/MvCameraControl_class.py b/camera/MvCameraControl_class.py index 2947b70..bc12318 100644 --- a/camera/MvCameraControl_class.py +++ b/camera/MvCameraControl_class.py @@ -47,9 +47,13 @@ class MvCamera(): # ch:初始化SDK | en: Initialize SDK @staticmethod def MV_CC_Initialize(): - MvCamCtrldll.MV_CC_Initialize.restype = c_int - # C原型:int __stdcall MV_CC_Initialize(); - return MvCamCtrldll.MV_CC_Initialize() + try: + MvCamCtrldll.MV_CC_Initialize.restype = c_int + # C原型:int __stdcall MV_CC_Initialize(); + return MvCamCtrldll.MV_CC_Initialize() + except Exception as e: + print(f"初始化SDK失败: {e}") + return -1 # ch:反初始化SDK | en: Finalize SDK @staticmethod diff --git a/ui/settings_ui.py b/ui/settings_ui.py index 70bb86a..efda7e8 100644 --- a/ui/settings_ui.py +++ b/ui/settings_ui.py @@ -3,7 +3,7 @@ from PySide6.QtWidgets import ( QTabWidget, QFrame, QFormLayout, QGroupBox, QRadioButton, QSpacerItem, QSizePolicy, QTableWidget, QTableWidgetItem, QHeaderView, QSlider, QCheckBox, QButtonGroup ) -from PySide6.QtGui import QFont, QBrush, QColor +from PySide6.QtGui import QFont, QBrush, QColor, QIntValidator from PySide6.QtCore import Qt, Signal, QSize class SettingsUI(QWidget): @@ -354,11 +354,71 @@ class SettingsUI(QWidget): self.plc_layout = QVBoxLayout(self.plc_tab) self.plc_layout.setContentsMargins(20, 20, 20, 20) - # 占位标签 - self.plc_placeholder = QLabel("PLC设置(待实现)") - self.plc_placeholder.setFont(self.normal_font) - self.plc_placeholder.setAlignment(Qt.AlignCenter) - self.plc_layout.addWidget(self.plc_placeholder) + # 创建Modbus配置组 + self.modbus_group = QGroupBox("Modbus 配置") + self.modbus_group.setFont(self.normal_font) + self.modbus_layout = QFormLayout(self.modbus_group) + self.modbus_layout.setContentsMargins(15, 20, 15, 15) + self.modbus_layout.setSpacing(15) + + # 主机地址输入框 + self.modbus_host_input = QLineEdit() + self.modbus_host_input.setFont(self.normal_font) + self.modbus_host_input.setPlaceholderText("请输入Modbus主机地址") + self.modbus_layout.addRow(QLabel("主机地址:"), self.modbus_host_input) + + # 端口输入框 + self.modbus_port_input = QLineEdit() + self.modbus_port_input.setFont(self.normal_font) + self.modbus_port_input.setPlaceholderText("请输入Modbus端口") + self.modbus_port_input.setValidator(QIntValidator(1, 65535)) + self.modbus_layout.addRow(QLabel("端口:"), self.modbus_port_input) + + # 测试连接按钮 + self.modbus_test_button = QPushButton("测试连接") + self.modbus_test_button.setFont(self.normal_font) + self.modbus_test_button.setStyleSheet(""" + QPushButton { + background-color: #2196f3; + color: white; + border: none; + border-radius: 3px; + padding: 5px 15px; + } + QPushButton:hover { + background-color: #1e88e5; + } + """) + self.modbus_layout.addRow("", self.modbus_test_button) + + # 添加Modbus配置组到布局 + self.plc_layout.addWidget(self.modbus_group) + + # 添加保存按钮 + self.plc_save_button = QPushButton("保存配置") + self.plc_save_button.setFont(self.normal_font) + self.plc_save_button.setFixedSize(120, 40) + self.plc_save_button.setStyleSheet(""" + QPushButton { + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + } + QPushButton:hover { + background-color: #45a049; + } + QPushButton:pressed { + background-color: #3d8b40; + } + """) + + # 添加按钮布局 + button_layout = QHBoxLayout() + button_layout.addStretch(1) + button_layout.addWidget(self.plc_save_button) + + self.plc_layout.addLayout(button_layout) self.plc_layout.addStretch(1) self.tab_widget.addTab(self.plc_tab, "PLC设置") diff --git a/utils/modbus_utils.py b/utils/modbus_utils.py index 5713f33..1c35adc 100644 --- a/utils/modbus_utils.py +++ b/utils/modbus_utils.py @@ -11,13 +11,13 @@ log.setLevel(logging.WARNING) # Modbus TCP 配置 class ModbusUtils: - - def __init__(self) -> None: + + def __init__(self, host=None, port=None) -> None: # 初始化 modbus 配置 config = ConfigLoader.get_instance() - self.MODBUS_HOST = config.get_value("modbus.host") - self.MODBUS_PORT = config.get_value("modbus.port") - + self.MODBUS_HOST = host if host is not None else config.get_value("modbus.host") + self.MODBUS_PORT = port if port is not None else int(config.get_value("modbus.port")) + def get_client(self): # 创建Modbus TCP客户端实例,指定服务器的IP地址和端口号 # client = ModbusTcpClient('localhost', port=5020) @@ -35,11 +35,10 @@ class ModbusUtils: return None # Or raise an exception return client - def close_client(self, client): # 关闭客户端连接 if client: - client.close() + client.close() # 新增十进制转成二进制 @staticmethod diff --git a/widgets/plc_settings_widget.py b/widgets/plc_settings_widget.py new file mode 100644 index 0000000..ca369ef --- /dev/null +++ b/widgets/plc_settings_widget.py @@ -0,0 +1,141 @@ +import logging +import json +import os +from PySide6.QtWidgets import QWidget, QMessageBox +from PySide6.QtCore import Signal +from utils.config_loader import ConfigLoader + +class PLCSettingsWidget(QWidget): + """PLC设置控制器""" + + # 定义信号 + settings_changed = Signal() # 设置变更信号 + + def __init__(self, parent=None): + """初始化控制器 + + Args: + parent: 父窗口 + """ + super().__init__(parent) + self.parent = parent + self.config = ConfigLoader.get_instance() + + # 获取UI控件引用 + self.modbus_host_input = parent.modbus_host_input + self.modbus_port_input = parent.modbus_port_input + self.modbus_test_button = parent.modbus_test_button + self.plc_save_button = parent.plc_save_button + + # 连接信号和槽 + self.connect_signals() + + # 加载配置 + self.load_config() + + def connect_signals(self): + """连接信号和槽""" + self.modbus_test_button.clicked.connect(self.test_modbus_connection) + self.plc_save_button.clicked.connect(self.save_config) + + def load_config(self): + """加载配置""" + try: + # 加载Modbus配置 + host = self.config.get_value("modbus.host") + port = self.config.get_value("modbus.port") + + self.modbus_host_input.setText(host if host else "localhost") + self.modbus_port_input.setText(str(port) if port else "502") + + logging.info("已加载PLC配置") + except Exception as e: + logging.error(f"加载PLC配置失败: {str(e)}") + QMessageBox.critical(self, "错误", f"加载PLC配置失败: {str(e)}") + + def save_config(self): + """保存配置""" + try: + # 获取输入值 + host = self.modbus_host_input.text().strip() + port = self.modbus_port_input.text().strip() + + # 验证输入 + if not host: + QMessageBox.warning(self, "警告", "请输入Modbus主机地址") + return + + if not port: + QMessageBox.warning(self, "警告", "请输入Modbus端口") + return + + try: + port_int = int(port) + if port_int < 1 or port_int > 65535: + QMessageBox.warning(self, "警告", "端口号必须在1-65535之间") + return + except ValueError: + QMessageBox.warning(self, "警告", "端口号必须是整数") + return + + # 更新配置 + self.config.set_value("modbus.host", host) + self.config.set_value("modbus.port", port) + self.config.save_config() + + # 发送信号 + self.settings_changed.emit() + + # 提示成功 + QMessageBox.information(self, "成功", "PLC配置已保存") + logging.info(f"已保存PLC配置: host={host}, port={port}") + except Exception as e: + logging.error(f"保存PLC配置失败: {str(e)}") + QMessageBox.critical(self, "错误", f"保存PLC配置失败: {str(e)}") + + def test_modbus_connection(self): + """测试Modbus连接""" + try: + # 获取输入值 + host = self.modbus_host_input.text().strip() + port = self.modbus_port_input.text().strip() + + # 验证输入 + if not host: + QMessageBox.warning(self, "警告", "请输入Modbus主机地址") + return + + if not port: + QMessageBox.warning(self, "警告", "请输入Modbus端口") + return + + try: + port_int = int(port) + except ValueError: + QMessageBox.warning(self, "警告", "端口号必须是整数") + return + + # 导入ModbusUtils + from utils.modbus_utils import ModbusUtils + + # 创建Modbus连接 + modbus = ModbusUtils(host=host, port=port_int) + client = modbus.get_client() + + if client: + QMessageBox.information(self, "成功", f"Modbus连接成功: {host}:{port}") + logging.info(f"Modbus连接测试成功: {host}:{port}") + else: + QMessageBox.warning(self, "警告", f"Modbus连接失败: {host}:{port}") + logging.warning(f"Modbus连接测试失败: {host}:{port}") + + # 关闭连接 + modbus.close_client(client) + except Exception as e: + logging.error(f"测试Modbus连接失败: {str(e)}") + QMessageBox.critical(self, "错误", f"测试Modbus连接失败: {str(e)}") + + def on_settings_changed(self): + """设置变更处理""" + # 重新加载配置 + self.load_config() \ No newline at end of file diff --git a/widgets/settings_widget.py b/widgets/settings_widget.py index 90c7308..dbeb9a3 100644 --- a/widgets/settings_widget.py +++ b/widgets/settings_widget.py @@ -1,5 +1,5 @@ from PySide6.QtWidgets import QMessageBox, QVBoxLayout -from PySide6.QtCore import Qt +from PySide6.QtCore import Qt, Signal import logging import json import os @@ -7,19 +7,29 @@ from ui.settings_ui import SettingsUI from utils.sql_utils import SQLUtils from widgets.inspection_settings_widget import InspectionSettingsWidget from widgets.pallet_type_settings_widget import PalletTypeSettingsWidget +from widgets.plc_settings_widget import PLCSettingsWidget from utils.config_loader import ConfigLoader from utils.app_mode import AppMode +from widgets.camera_settings_widget import CameraSettingsWidget +from widgets.serial_settings_widget import SerialSettingsWidget class SettingsWidget(SettingsUI): + # 定义信号 + settings_changed = Signal() + def __init__(self, parent=None): + """初始化设置窗口""" super().__init__(parent) self.parent = parent logging.info("正在初始化SettingsWidget") - # 创建检验设置部件 - logging.info("创建InspectionSettingsWidget实例") - self.inspection_settings = InspectionSettingsWidget() + # 创建子设置控制器 + self.camera_settings = CameraSettingsWidget(self) + self.serial_settings = SerialSettingsWidget(self) + self.inspection_settings = InspectionSettingsWidget(self) + self.pallet_type_settings = PalletTypeSettingsWidget(self) + self.plc_settings = PLCSettingsWidget(self) # 移除临时占位符标签并添加检验设置部件 if hasattr(self, 'inspection_placeholder'): @@ -60,7 +70,7 @@ class SettingsWidget(SettingsUI): # 加载配置文件 self.config_loader = ConfigLoader.get_instance() - # 连接信号和槽 + # 连接信号 self.connect_signals() # 初始化数据库类型UI状态 @@ -72,6 +82,14 @@ class SettingsWidget(SettingsUI): logging.info("SettingsWidget初始化完成") def connect_signals(self): + """连接信号和槽""" + # 连接子设置控制器的信号 + self.camera_settings.settings_changed.connect(self.on_settings_changed) + self.serial_settings.settings_changed.connect(self.on_settings_changed) + self.inspection_settings.settings_changed.connect(self.on_settings_changed) + self.pallet_type_settings.settings_changed.connect(self.on_settings_changed) + self.plc_settings.settings_changed.connect(self.on_settings_changed) + # 数据库类型选择 self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state) @@ -353,4 +371,10 @@ class SettingsWidget(SettingsUI): def back_to_main(self): """返回主页""" if self.parent and hasattr(self.parent, 'show_main_page'): - self.parent.show_main_page() \ No newline at end of file + self.parent.show_main_page() + + def on_settings_changed(self): + """处理设置变更信号""" + logging.info("设置已变更,发送settings_changed信号") + # 发送信号 + self.settings_changed.emit() \ No newline at end of file