feat:完成相机配置
This commit is contained in:
parent
320d715f83
commit
074b656bbc
@ -107,8 +107,10 @@ class CameraOperation:
|
|||||||
return MV_E_CALLORDER
|
return MV_E_CALLORDER
|
||||||
|
|
||||||
# ch:选择设备并创建句柄 | en:Select device and create handle
|
# ch:选择设备并创建句柄 | en:Select device and create handle
|
||||||
|
# 确保索引是整数类型
|
||||||
nConnectionNum = int(self.n_connect_num)
|
nConnectionNum = int(self.n_connect_num)
|
||||||
stDeviceList = cast(self.st_device_list.pDeviceInfo[int(nConnectionNum)],
|
print(f"打开设备,使用设备索引: {nConnectionNum}, 类型: {type(nConnectionNum)}")
|
||||||
|
stDeviceList = cast(self.st_device_list.pDeviceInfo[nConnectionNum],
|
||||||
POINTER(MV_CC_DEVICE_INFO)).contents
|
POINTER(MV_CC_DEVICE_INFO)).contents
|
||||||
self.obj_cam = MvCamera()
|
self.obj_cam = MvCamera()
|
||||||
ret = self.obj_cam.MV_CC_CreateHandle(stDeviceList)
|
ret = self.obj_cam.MV_CC_CreateHandle(stDeviceList)
|
||||||
|
|||||||
@ -49,8 +49,8 @@
|
|||||||
"default_framerate": 30
|
"default_framerate": 30
|
||||||
},
|
},
|
||||||
"modbus": {
|
"modbus": {
|
||||||
"host": "localhost",
|
"host": "192.168.2.88",
|
||||||
"port": "5020"
|
"port": "502"
|
||||||
},
|
},
|
||||||
"serial": {
|
"serial": {
|
||||||
"keyboard": {
|
"keyboard": {
|
||||||
|
|||||||
BIN
db/jtDB.db
BIN
db/jtDB.db
Binary file not shown.
@ -39,6 +39,7 @@ class SettingsUI(QWidget):
|
|||||||
self.create_database_tab()
|
self.create_database_tab()
|
||||||
self.create_inspection_tab()
|
self.create_inspection_tab()
|
||||||
self.create_plc_tab()
|
self.create_plc_tab()
|
||||||
|
self.create_electricity_tab() # 新增电量监控标签页
|
||||||
self.create_push_tab()
|
self.create_push_tab()
|
||||||
self.create_auth_tab()
|
self.create_auth_tab()
|
||||||
self.create_user_tab()
|
self.create_user_tab()
|
||||||
@ -64,6 +65,7 @@ class SettingsUI(QWidget):
|
|||||||
|
|
||||||
self.refresh_button = QPushButton("刷新设备")
|
self.refresh_button = QPushButton("刷新设备")
|
||||||
self.refresh_button.setFont(self.normal_font)
|
self.refresh_button.setFont(self.normal_font)
|
||||||
|
self.refresh_button.setObjectName("refresh_button") # 设置对象名称,方便查找
|
||||||
|
|
||||||
self.camera_select_layout.addWidget(self.camera_label)
|
self.camera_select_layout.addWidget(self.camera_label)
|
||||||
self.camera_select_layout.addWidget(self.camera_combo)
|
self.camera_select_layout.addWidget(self.camera_combo)
|
||||||
@ -483,6 +485,24 @@ class SettingsUI(QWidget):
|
|||||||
|
|
||||||
self.tab_widget.addTab(self.param_tab, "参数配置")
|
self.tab_widget.addTab(self.param_tab, "参数配置")
|
||||||
|
|
||||||
|
def create_electricity_tab(self):
|
||||||
|
"""创建电量监控选项卡"""
|
||||||
|
# 电量监控选项卡
|
||||||
|
self.electricity_tab = QWidget()
|
||||||
|
self.electricity_layout = QVBoxLayout(self.electricity_tab)
|
||||||
|
self.electricity_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.electricity_layout.setSpacing(0)
|
||||||
|
|
||||||
|
# 添加一个临时提示标签,表示此处将由ElectricitySettingsUI替换
|
||||||
|
self.electricity_placeholder = QLabel("正在加载电量监控设置...")
|
||||||
|
self.electricity_placeholder.setFont(self.normal_font)
|
||||||
|
self.electricity_placeholder.setAlignment(Qt.AlignCenter)
|
||||||
|
self.electricity_placeholder.setStyleSheet("color: #888888; padding: 20px;")
|
||||||
|
self.electricity_layout.addWidget(self.electricity_placeholder)
|
||||||
|
|
||||||
|
# 添加到选项卡
|
||||||
|
self.tab_widget.addTab(self.electricity_tab, "电量监控")
|
||||||
|
|
||||||
def create_pallet_type_tab(self):
|
def create_pallet_type_tab(self):
|
||||||
# 托盘类型设置选项卡
|
# 托盘类型设置选项卡
|
||||||
self.pallet_type_tab = QWidget()
|
self.pallet_type_tab = QWidget()
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
import ctypes
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
|
|
||||||
# 添加相机模块路径
|
# 添加相机模块路径
|
||||||
@ -49,7 +51,7 @@ class CameraManager:
|
|||||||
logging.info("相机SDK已初始化")
|
logging.info("相机SDK已初始化")
|
||||||
|
|
||||||
def enum_devices(self):
|
def enum_devices(self):
|
||||||
"""枚举相机设备"""
|
"""枚举相机设备,完全参考BasicDemo.py的enum_devices实现"""
|
||||||
try:
|
try:
|
||||||
# 确保先关闭任何已打开的相机
|
# 确保先关闭任何已打开的相机
|
||||||
if self.isOpen:
|
if self.isOpen:
|
||||||
@ -71,24 +73,27 @@ class CameraManager:
|
|||||||
|
|
||||||
logging.info(f"找到 {self.deviceList.nDeviceNum} 个相机设备")
|
logging.info(f"找到 {self.deviceList.nDeviceNum} 个相机设备")
|
||||||
|
|
||||||
|
# 定义解码函数
|
||||||
|
def decoding_char(c_ubyte_value):
|
||||||
|
c_char_p_value = ctypes.cast(c_ubyte_value, ctypes.c_char_p)
|
||||||
|
try:
|
||||||
|
decode_str = c_char_p_value.value.decode('gbk') # 中文字符
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
decode_str = str(c_char_p_value.value)
|
||||||
|
return decode_str
|
||||||
|
|
||||||
# 构造设备信息列表
|
# 构造设备信息列表
|
||||||
devices_info = []
|
devices_info = []
|
||||||
for i in range(0, self.deviceList.nDeviceNum):
|
for i in range(0, self.deviceList.nDeviceNum):
|
||||||
mvcc_dev_info = cast(self.deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
|
mvcc_dev_info = cast(self.deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
|
||||||
|
|
||||||
|
# 详细日志
|
||||||
|
logging.debug(f"设备 {i} 类型: {mvcc_dev_info.nTLayerType}")
|
||||||
|
|
||||||
if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
|
if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
|
||||||
# GigE相机
|
# GigE相机
|
||||||
user_defined_name = ""
|
user_defined_name = decoding_char(mvcc_dev_info.SpecialInfo.stGigEInfo.chUserDefinedName)
|
||||||
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chUserDefinedName:
|
model_name = decoding_char(mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName)
|
||||||
if per == 0:
|
|
||||||
break
|
|
||||||
user_defined_name = user_defined_name + chr(per)
|
|
||||||
|
|
||||||
model_name = ""
|
|
||||||
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
|
|
||||||
if per == 0:
|
|
||||||
break
|
|
||||||
model_name = model_name + chr(per)
|
|
||||||
|
|
||||||
nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
|
nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
|
||||||
nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
|
nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
|
||||||
@ -96,48 +101,81 @@ class CameraManager:
|
|||||||
nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
|
nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
|
||||||
ip = f"{nip1}.{nip2}.{nip3}.{nip4}"
|
ip = f"{nip1}.{nip2}.{nip3}.{nip4}"
|
||||||
|
|
||||||
|
display = f"[{i}]GigE: {user_defined_name} {model_name} ({ip})"
|
||||||
|
logging.debug(f"GigE相机: {display}")
|
||||||
|
|
||||||
device_info = {
|
device_info = {
|
||||||
"index": i,
|
"index": i,
|
||||||
"type": "GigE",
|
"type": "GigE",
|
||||||
"name": user_defined_name,
|
"name": user_defined_name,
|
||||||
"model": model_name,
|
"model": model_name,
|
||||||
"ip": ip,
|
"ip": ip,
|
||||||
"display": f"[{i}]GigE: {user_defined_name} {model_name} ({ip})"
|
"display": display
|
||||||
}
|
}
|
||||||
devices_info.append(device_info)
|
devices_info.append(device_info)
|
||||||
|
|
||||||
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
|
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
|
||||||
# USB相机
|
# USB相机
|
||||||
user_defined_name = ""
|
user_defined_name = decoding_char(mvcc_dev_info.SpecialInfo.stUsb3VInfo.chUserDefinedName)
|
||||||
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chUserDefinedName:
|
model_name = decoding_char(mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName)
|
||||||
if per == 0:
|
|
||||||
break
|
|
||||||
user_defined_name = user_defined_name + chr(per)
|
|
||||||
|
|
||||||
model_name = ""
|
# 序列号
|
||||||
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
|
strSerialNumber = ""
|
||||||
|
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
|
||||||
if per == 0:
|
if per == 0:
|
||||||
break
|
break
|
||||||
model_name = model_name + chr(per)
|
strSerialNumber = strSerialNumber + chr(per)
|
||||||
|
|
||||||
|
display = f"[{i}]USB: {user_defined_name} {model_name} ({strSerialNumber})"
|
||||||
|
logging.debug(f"USB相机: {display}")
|
||||||
|
|
||||||
device_info = {
|
device_info = {
|
||||||
"index": i,
|
"index": i,
|
||||||
"type": "USB",
|
"type": "USB",
|
||||||
"name": user_defined_name,
|
"name": user_defined_name,
|
||||||
"model": model_name,
|
"model": model_name,
|
||||||
"display": f"[{i}]USB: {user_defined_name} {model_name}"
|
"serial": strSerialNumber,
|
||||||
|
"display": display
|
||||||
}
|
}
|
||||||
devices_info.append(device_info)
|
devices_info.append(device_info)
|
||||||
|
|
||||||
|
elif mvcc_dev_info.nTLayerType == MV_GENTL_CAMERALINK_DEVICE:
|
||||||
|
# CameraLink相机
|
||||||
|
user_defined_name = decoding_char(mvcc_dev_info.SpecialInfo.stCMLInfo.chUserDefinedName)
|
||||||
|
model_name = decoding_char(mvcc_dev_info.SpecialInfo.stCMLInfo.chModelName)
|
||||||
|
|
||||||
|
strSerialNumber = ""
|
||||||
|
for per in mvcc_dev_info.SpecialInfo.stCMLInfo.chSerialNumber:
|
||||||
|
if per == 0:
|
||||||
|
break
|
||||||
|
strSerialNumber = strSerialNumber + chr(per)
|
||||||
|
|
||||||
|
display = f"[{i}]CML: {user_defined_name} {model_name} ({strSerialNumber})"
|
||||||
|
logging.debug(f"CML相机: {display}")
|
||||||
|
|
||||||
|
device_info = {
|
||||||
|
"index": i,
|
||||||
|
"type": "CML",
|
||||||
|
"name": user_defined_name,
|
||||||
|
"model": model_name,
|
||||||
|
"serial": strSerialNumber,
|
||||||
|
"display": display
|
||||||
|
}
|
||||||
|
devices_info.append(device_info)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 其他类型相机
|
# 其他类型相机
|
||||||
|
display = f"[{i}]Other"
|
||||||
device_info = {
|
device_info = {
|
||||||
"index": i,
|
"index": i,
|
||||||
"type": "Other",
|
"type": "Other",
|
||||||
"display": f"[{i}]Other"
|
"display": display
|
||||||
}
|
}
|
||||||
devices_info.append(device_info)
|
devices_info.append(device_info)
|
||||||
|
logging.debug(f"其他类型相机: {display}")
|
||||||
|
|
||||||
|
# 添加详细日志
|
||||||
|
logging.debug(f"枚举到的设备数量: {len(devices_info)}")
|
||||||
return devices_info
|
return devices_info
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -146,7 +184,7 @@ class CameraManager:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def open_device(self, device_index):
|
def open_device(self, device_index):
|
||||||
"""打开相机设备
|
"""打开相机设备,参考BasicDemo.py的open_device实现
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
device_index: 设备索引
|
device_index: 设备索引
|
||||||
@ -159,14 +197,18 @@ class CameraManager:
|
|||||||
logging.warning("相机已经打开!")
|
logging.warning("相机已经打开!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查设备索引是否有效
|
# 确保有效的设备索引
|
||||||
if device_index < 0 or (self.deviceList and device_index >= self.deviceList.nDeviceNum):
|
if device_index < 0 or self.deviceList is None or device_index >= self.deviceList.nDeviceNum:
|
||||||
logging.error(f"无效的设备索引: {device_index}")
|
error_msg = f"无效的设备索引: {device_index}, 设备列表: {self.deviceList is not None}"
|
||||||
|
if self.deviceList:
|
||||||
|
error_msg += f", 设备数量: {self.deviceList.nDeviceNum}"
|
||||||
|
logging.error(error_msg)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logging.debug(f"准备打开相机,设备索引: {device_index}")
|
logging.info(f"开始打开相机,设备索引: {device_index}")
|
||||||
|
|
||||||
|
# 设置当前选中的相机索引
|
||||||
self.nSelCamIndex = device_index
|
self.nSelCamIndex = device_index
|
||||||
|
|
||||||
# 创建相机操作对象
|
# 创建相机操作对象
|
||||||
@ -178,14 +220,25 @@ class CameraManager:
|
|||||||
self.isOpen = False
|
self.isOpen = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 设置连续模式
|
# 设置连续模式 (非触发模式)
|
||||||
self.obj_cam_operation.Set_trigger_mode(False)
|
ret = self.obj_cam_operation.Set_trigger_mode(False)
|
||||||
|
if ret != 0:
|
||||||
|
error_msg = f"设置连续模式失败! 错误码: 0x{ret:x}"
|
||||||
|
logging.error(error_msg)
|
||||||
|
# 出错时关闭设备
|
||||||
|
self.obj_cam_operation.Close_device()
|
||||||
|
self.isOpen = False
|
||||||
|
return False
|
||||||
|
|
||||||
# 获取参数
|
# 获取参数
|
||||||
self.obj_cam_operation.Get_parameter()
|
ret = self.obj_cam_operation.Get_parameter()
|
||||||
|
if ret != 0:
|
||||||
|
error_msg = f"获取相机参数失败! 错误码: 0x{ret:x}"
|
||||||
|
logging.error(error_msg)
|
||||||
|
# 继续执行,不返回失败
|
||||||
|
|
||||||
self.isOpen = True
|
self.isOpen = True
|
||||||
logging.info(f"相机已打开,设备索引: {device_index}")
|
logging.info(f"相机已成功打开,设备索引: {device_index}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -351,4 +404,52 @@ class CameraManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"设置相机参数时发生异常: {str(e)}"
|
error_msg = f"设置相机参数时发生异常: {str(e)}"
|
||||||
logging.error(error_msg)
|
logging.error(error_msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save_params_to_config(self, exposure, gain, frame_rate):
|
||||||
|
"""保存相机参数到配置文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exposure: 曝光值(滑块值)
|
||||||
|
gain: 增益(滑块值)
|
||||||
|
frame_rate: 帧率(滑块值)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功保存参数
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 创建相机参数配置
|
||||||
|
config = {
|
||||||
|
"exposure": exposure,
|
||||||
|
"gain": gain,
|
||||||
|
"frame_rate": frame_rate
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保存到配置文件
|
||||||
|
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "camera_config.json")
|
||||||
|
os.makedirs(os.path.dirname(config_path), exist_ok=True)
|
||||||
|
|
||||||
|
# 检查文件是否存在并读取
|
||||||
|
if os.path.exists(config_path):
|
||||||
|
with open(config_path, 'r', encoding='utf-8') as f:
|
||||||
|
try:
|
||||||
|
full_config = json.load(f)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
full_config = {}
|
||||||
|
else:
|
||||||
|
full_config = {}
|
||||||
|
|
||||||
|
# 更新配置
|
||||||
|
full_config["camera_params"] = config
|
||||||
|
|
||||||
|
# 写入文件
|
||||||
|
with open(config_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(full_config, f, indent=4, ensure_ascii=False)
|
||||||
|
|
||||||
|
logging.info(f"相机参数已保存到配置文件: {config_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"保存相机参数到配置文件时发生异常: {str(e)}"
|
||||||
|
logging.error(error_msg)
|
||||||
return False
|
return False
|
||||||
@ -28,27 +28,91 @@ from ui.settings_ui import SettingsUI
|
|||||||
from widgets.camera_manager import CameraManager
|
from widgets.camera_manager import CameraManager
|
||||||
|
|
||||||
|
|
||||||
class CameraSettingsWidget(SettingsUI):
|
from PySide6.QtCore import QObject
|
||||||
"""相机设置控制器,管理相机设置并提供与主窗口相机显示部分的通信"""
|
|
||||||
|
class CameraSettingsWidget(QObject):
|
||||||
|
"""相机设置控制器,管理相机设置并提供与主窗口相机显示部分的通信
|
||||||
|
注意:这是一个QObject控制器,不是QWidget,只处理逻辑,UI控件需要从父组件获取"""
|
||||||
|
|
||||||
# 定义信号
|
# 定义信号
|
||||||
signal_camera_connection = Signal(bool, str) # 相机连接状态信号 (是否连接, 错误消息)
|
signal_camera_connection = Signal(bool, str) # 相机连接状态信号 (是否连接, 错误消息)
|
||||||
signal_camera_params_changed = Signal(float, float, float) # 相机参数变化信号 (曝光, 增益, 帧率)
|
signal_camera_params_changed = Signal(float, float, float) # 相机参数变化信号 (曝光, 增益, 帧率)
|
||||||
signal_camera_error = Signal(str) # 相机错误信号
|
signal_camera_error = Signal(str) # 相机错误信号
|
||||||
settings_changed = Signal() # 设置变更信号,与 SettingsWindow 兼容
|
settings_changed = Signal() # 设置变更信号,与 SettingsWindow 兼容
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
"""初始化相机设置控制器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
parent: 父组件,需要包含所有必要的UI控件
|
||||||
|
"""
|
||||||
|
# 作为QObject初始化
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
|
# 记录父组件引用
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
# 获取相机管理器实例
|
# 获取相机管理器实例
|
||||||
self.camera_manager = CameraManager.get_instance()
|
self.camera_manager = CameraManager.get_instance()
|
||||||
|
|
||||||
# 初始化UI控件状态
|
# 初始化日志记录
|
||||||
self.update_controls()
|
logging.debug("CameraSettingsWidget初始化开始")
|
||||||
|
|
||||||
|
# 从父组件获取所有需要的UI控件
|
||||||
|
if parent is not None:
|
||||||
|
logging.info(f"父控件类型: {type(parent).__name__}")
|
||||||
|
|
||||||
|
# 从父组件获取所有需要的UI控件
|
||||||
|
self.camera_combo = getattr(parent, 'camera_combo', None)
|
||||||
|
self.refresh_button = getattr(parent, 'refresh_button', None)
|
||||||
|
self.open_button = getattr(parent, 'open_button', None)
|
||||||
|
self.close_button = getattr(parent, 'close_button', None)
|
||||||
|
self.test_button = getattr(parent, 'test_button', None)
|
||||||
|
self.exposure_slider = getattr(parent, 'exposure_slider', None)
|
||||||
|
self.gain_slider = getattr(parent, 'gain_slider', None)
|
||||||
|
self.framerate_slider = getattr(parent, 'framerate_slider', None)
|
||||||
|
self.exposure_value = getattr(parent, 'exposure_value', None)
|
||||||
|
self.gain_value = getattr(parent, 'gain_value', None)
|
||||||
|
self.framerate_value = getattr(parent, 'framerate_value', None)
|
||||||
|
self.get_params_button = getattr(parent, 'get_params_button', None)
|
||||||
|
self.set_params_button = getattr(parent, 'set_params_button', None)
|
||||||
|
self.save_camera_button = getattr(parent, 'save_camera_button', None)
|
||||||
|
self.preview_frame = getattr(parent, 'preview_frame', None)
|
||||||
|
|
||||||
|
# 检查是否成功获取到了所有必要的UI控件
|
||||||
|
if self.camera_combo is None:
|
||||||
|
logging.error("未能从父组件获取camera_combo")
|
||||||
|
else:
|
||||||
|
logging.info(f"获取到父组件的camera_combo: ID={id(self.camera_combo)}, 项目数={self.camera_combo.count()}")
|
||||||
|
|
||||||
|
# 测试向下拉框添加项目
|
||||||
|
try:
|
||||||
|
self.camera_combo.addItem("控制器初始化测试项")
|
||||||
|
logging.info(f"成功添加测试项到camera_combo,当前项目数={self.camera_combo.count()}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"添加测试项失败: {e}")
|
||||||
|
else:
|
||||||
|
logging.error("CameraSettingsWidget必须有一个包含UI控件的父组件")
|
||||||
|
# 创建缺少的UI控件引用,这些引用将为None
|
||||||
|
self.camera_combo = None
|
||||||
|
self.refresh_button = None
|
||||||
|
self.open_button = None
|
||||||
|
self.close_button = None
|
||||||
|
self.test_button = None
|
||||||
|
self.exposure_slider = None
|
||||||
|
self.gain_slider = None
|
||||||
|
self.framerate_slider = None
|
||||||
|
self.exposure_value = None
|
||||||
|
self.gain_value = None
|
||||||
|
self.framerate_value = None
|
||||||
|
self.get_params_button = None
|
||||||
|
self.set_params_button = None
|
||||||
|
self.save_camera_button = None
|
||||||
|
self.preview_frame = None
|
||||||
|
|
||||||
# 连接信号和槽
|
# 连接信号和槽
|
||||||
self.connect_signals()
|
self.connect_signals()
|
||||||
|
|
||||||
# 初始化相机参数范围
|
# 初始化相机参数范围
|
||||||
self.frame_rate_min = 1.0
|
self.frame_rate_min = 1.0
|
||||||
self.frame_rate_max = 60.0
|
self.frame_rate_max = 60.0
|
||||||
@ -63,7 +127,8 @@ class CameraSettingsWidget(SettingsUI):
|
|||||||
def connect_signals(self):
|
def connect_signals(self):
|
||||||
"""连接信号和槽"""
|
"""连接信号和槽"""
|
||||||
# 设备选择和刷新
|
# 设备选择和刷新
|
||||||
self.refresh_button.clicked.connect(self.refresh_devices)
|
if hasattr(self, 'refresh_button'):
|
||||||
|
self.refresh_button.clicked.connect(self.refresh_devices)
|
||||||
|
|
||||||
# 相机控制按钮
|
# 相机控制按钮
|
||||||
self.open_button.clicked.connect(self.open_camera)
|
self.open_button.clicked.connect(self.open_camera)
|
||||||
@ -79,259 +144,315 @@ class CameraSettingsWidget(SettingsUI):
|
|||||||
self.get_params_button.clicked.connect(self.get_camera_params)
|
self.get_params_button.clicked.connect(self.get_camera_params)
|
||||||
self.set_params_button.clicked.connect(self.set_camera_params)
|
self.set_params_button.clicked.connect(self.set_camera_params)
|
||||||
self.save_camera_button.clicked.connect(self.save_camera_params)
|
self.save_camera_button.clicked.connect(self.save_camera_params)
|
||||||
|
|
||||||
def refresh_devices(self):
|
def refresh_devices(self):
|
||||||
"""刷新设备列表"""
|
"""刷新设备列表"""
|
||||||
self.camera_combo.clear()
|
logging.info("【设备刷新】开始...")
|
||||||
|
|
||||||
# 枚举设备
|
# 直接检查是否能访问正确的combobox
|
||||||
devices_info = self.camera_manager.enum_devices()
|
if not hasattr(self, 'camera_combo') or self.camera_combo is None:
|
||||||
|
logging.error("【设备刷新】无法访问camera_combo,尝试从父组件获取")
|
||||||
|
|
||||||
|
# 尝试从父组件获取
|
||||||
|
if hasattr(self, 'parent') and self.parent is not None:
|
||||||
|
if hasattr(self.parent, 'camera_combo'):
|
||||||
|
self.camera_combo = self.parent.camera_combo
|
||||||
|
logging.info(f"【设备刷新】已从父组件获取camera_combo: {id(self.camera_combo)}")
|
||||||
|
else:
|
||||||
|
logging.error("【设备刷新】父组件也没有camera_combo")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
logging.error("【设备刷新】无法获取camera_combo且没有父组件")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 直接测试下拉框是否可用
|
||||||
|
try:
|
||||||
|
# 先清理
|
||||||
|
self.camera_combo.clear()
|
||||||
|
|
||||||
|
# 添加一个测试项
|
||||||
|
self.camera_combo.addItem("刷新中...")
|
||||||
|
logging.info(f"【设备刷新】成功添加测试项,当前项目数={self.camera_combo.count()}")
|
||||||
|
|
||||||
|
# 更新UI
|
||||||
|
self.camera_combo.update()
|
||||||
|
self.camera_combo.repaint()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"【设备刷新】测试下拉框失败: {e}")
|
||||||
|
|
||||||
if not devices_info:
|
# 1. 枚举设备
|
||||||
self.camera_combo.addItem("未发现相机设备")
|
try:
|
||||||
self.camera_combo.setEnabled(False)
|
devices_info = self.camera_manager.enum_devices()
|
||||||
self.open_button.setEnabled(False)
|
if not devices_info:
|
||||||
return
|
logging.warning("【设备刷新】未发现任何相机设备。")
|
||||||
|
devices_info = []
|
||||||
# 添加设备到下拉框
|
except Exception as e:
|
||||||
for device in devices_info:
|
logging.error(f"【设备刷新】枚举设备时发生错误: {e}")
|
||||||
self.camera_combo.addItem(device["display"], device["index"])
|
devices_info = []
|
||||||
|
|
||||||
self.camera_combo.setEnabled(True)
|
# 2. 准备要显示到下拉列表的数据
|
||||||
self.open_button.setEnabled(True)
|
devList = []
|
||||||
|
if devices_info:
|
||||||
# 更新控件状态
|
for device in devices_info:
|
||||||
self.update_controls()
|
devList.append(device["display"])
|
||||||
|
logging.info(f"【设备刷新】找到 {len(devList)} 个设备: {devList}")
|
||||||
|
else:
|
||||||
|
devList.append("未发现相机设备")
|
||||||
|
logging.info(f"【设备刷新】将显示默认值 '未发现相机设备'")
|
||||||
|
|
||||||
|
# 3. 更新UI上的下拉列表
|
||||||
|
try:
|
||||||
|
if hasattr(self, 'camera_combo') and self.camera_combo is not None:
|
||||||
|
logging.info(f"【设备刷新】开始更新下拉列表,当前状态: 项目数={self.camera_combo.count()}, 是否可见={self.camera_combo.isVisible()}")
|
||||||
|
|
||||||
|
self.camera_combo.blockSignals(True)
|
||||||
|
self.camera_combo.clear()
|
||||||
|
|
||||||
|
# 确保项目数清零
|
||||||
|
if self.camera_combo.count() > 0:
|
||||||
|
logging.warning(f"【设备刷新】clear()后项目数仍为 {self.camera_combo.count()}")
|
||||||
|
|
||||||
|
# 直接添加项目 - 单个添加,避免批量添加可能的问题
|
||||||
|
for item in devList:
|
||||||
|
self.camera_combo.addItem(item)
|
||||||
|
logging.debug(f"【设备刷新】已添加项目: {item}")
|
||||||
|
|
||||||
|
# 确保设置当前项目
|
||||||
|
if self.camera_combo.count() > 0:
|
||||||
|
self.camera_combo.setCurrentIndex(0)
|
||||||
|
logging.info(f"【设备刷新】已设置当前索引为0,显示文本: {self.camera_combo.currentText()}")
|
||||||
|
else:
|
||||||
|
logging.error("【设备刷新】未能添加任何项目到下拉列表")
|
||||||
|
|
||||||
|
self.camera_combo.blockSignals(False)
|
||||||
|
|
||||||
|
# 强制更新UI
|
||||||
|
self.camera_combo.update()
|
||||||
|
self.camera_combo.repaint()
|
||||||
|
|
||||||
|
# 确保ComboBox有足够的尺寸显示内容
|
||||||
|
self.camera_combo.adjustSize()
|
||||||
|
|
||||||
|
logging.info(f"【设备刷新】下拉列表更新完成。当前项目数: {self.camera_combo.count()}, 当前文本: {self.camera_combo.currentText()}")
|
||||||
|
else:
|
||||||
|
logging.error("【设备刷新】无法更新下拉列表,camera_combo不存在")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"【设备刷新】更新下拉列表时发生错误: {e}")
|
||||||
|
|
||||||
|
# 4. 更新其他控件的状态
|
||||||
|
try:
|
||||||
|
self.update_controls()
|
||||||
|
logging.info("【设备刷新】控件状态已更新。")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"【设备刷新】更新控件状态时发生错误: {e}")
|
||||||
|
|
||||||
|
# 5. 如果下拉列表仍然为空,尝试最后一次强制添加
|
||||||
|
try:
|
||||||
|
if hasattr(self, 'camera_combo') and self.camera_combo is not None:
|
||||||
|
if self.camera_combo.count() == 0:
|
||||||
|
logging.warning("【设备刷新】下拉列表仍然为空,尝试强制添加项目")
|
||||||
|
self.camera_combo.addItem("未发现相机设备(强制添加)")
|
||||||
|
self.camera_combo.setCurrentIndex(0)
|
||||||
|
self.camera_combo.update()
|
||||||
|
self.camera_combo.repaint()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"【设备刷新】强制添加项目时发生错误: {e}")
|
||||||
|
|
||||||
def get_selected_device_index(self):
|
def get_selected_device_index(self):
|
||||||
"""获取当前选中的设备索引"""
|
"""获取当前选中的设备索引,参考BasicDemo.py的TxtWrapBy实现"""
|
||||||
if self.camera_combo.count() == 0:
|
try:
|
||||||
|
if not hasattr(self, 'camera_combo') or self.camera_combo is None:
|
||||||
|
logging.error("无法获取设备索引:camera_combo不存在")
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if self.camera_combo.count() == 0:
|
||||||
|
logging.warning("设备下拉列表为空")
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if self.camera_combo.currentText() == "未发现相机设备":
|
||||||
|
return -1
|
||||||
|
|
||||||
|
current_text = self.camera_combo.currentText()
|
||||||
|
start = current_text.find("[") + 1
|
||||||
|
end = current_text.find("]", start)
|
||||||
|
|
||||||
|
if start <= 0 or end <= 0 or start >= end:
|
||||||
|
logging.error(f"设备文本格式不正确: '{current_text}'")
|
||||||
|
return -1
|
||||||
|
|
||||||
|
return int(current_text[start:end])
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"获取设备索引时出错: {e}, 文本: '{self.camera_combo.currentText() if hasattr(self, 'camera_combo') and self.camera_combo is not None else 'N/A'}'")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
return self.camera_combo.currentData()
|
|
||||||
|
|
||||||
def update_controls(self):
|
def update_controls(self):
|
||||||
"""更新控件状态"""
|
"""更新控件状态"""
|
||||||
is_open = self.camera_manager.isOpen
|
is_open = self.camera_manager.isOpen
|
||||||
is_grabbing = self.camera_manager.isGrabbing
|
is_grabbing = self.camera_manager.isGrabbing
|
||||||
|
|
||||||
|
# 使用安全的方式访问控件
|
||||||
|
if hasattr(self, 'refresh_button') and self.refresh_button is not None:
|
||||||
|
self.refresh_button.setEnabled(not is_open)
|
||||||
|
|
||||||
# 设备选择和刷新
|
if hasattr(self, 'camera_combo') and self.camera_combo is not None:
|
||||||
self.camera_combo.setEnabled(not is_open)
|
self.camera_combo.setEnabled(not is_open)
|
||||||
self.refresh_button.setEnabled(not is_open)
|
|
||||||
|
|
||||||
# 相机控制按钮
|
has_valid_selection = self.get_selected_device_index() != -1
|
||||||
self.open_button.setEnabled(not is_open and self.camera_combo.count() > 0 and self.camera_combo.currentData() is not None)
|
|
||||||
self.close_button.setEnabled(is_open)
|
|
||||||
self.test_button.setEnabled(is_open and not is_grabbing)
|
|
||||||
|
|
||||||
# 参数滑块
|
if hasattr(self, 'open_button') and self.open_button is not None:
|
||||||
self.exposure_slider.setEnabled(is_open)
|
self.open_button.setEnabled(not is_open and has_valid_selection)
|
||||||
self.gain_slider.setEnabled(is_open)
|
|
||||||
self.framerate_slider.setEnabled(is_open)
|
|
||||||
|
|
||||||
# 参数操作按钮
|
if hasattr(self, 'close_button') and self.close_button is not None:
|
||||||
self.get_params_button.setEnabled(is_open)
|
self.close_button.setEnabled(is_open)
|
||||||
self.set_params_button.setEnabled(is_open)
|
|
||||||
self.save_camera_button.setEnabled(is_open)
|
if hasattr(self, 'test_button') and self.test_button is not None:
|
||||||
|
self.test_button.setEnabled(is_open and not is_grabbing)
|
||||||
|
|
||||||
|
if hasattr(self, 'get_params_button') and self.get_params_button is not None:
|
||||||
|
self.get_params_button.setEnabled(is_open)
|
||||||
|
|
||||||
|
if hasattr(self, 'set_params_button') and self.set_params_button is not None:
|
||||||
|
self.set_params_button.setEnabled(is_open)
|
||||||
|
|
||||||
|
if hasattr(self, 'save_camera_button') and self.save_camera_button is not None:
|
||||||
|
self.save_camera_button.setEnabled(is_open)
|
||||||
|
|
||||||
|
if hasattr(self, 'exposure_slider') and self.exposure_slider is not None:
|
||||||
|
self.exposure_slider.setEnabled(is_open)
|
||||||
|
|
||||||
|
if hasattr(self, 'gain_slider') and self.gain_slider is not None:
|
||||||
|
self.gain_slider.setEnabled(is_open)
|
||||||
|
|
||||||
|
if hasattr(self, 'framerate_slider') and self.framerate_slider is not None:
|
||||||
|
self.framerate_slider.setEnabled(is_open)
|
||||||
|
|
||||||
def open_camera(self):
|
def open_camera(self):
|
||||||
"""打开相机"""
|
"""打开相机,参考BasicDemo.py实现"""
|
||||||
if self.camera_manager.isOpen:
|
if self.camera_manager.isOpen:
|
||||||
QMessageBox.warning(self, "错误", "相机已经打开!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
device_index = self.get_selected_device_index()
|
device_index = self.get_selected_device_index()
|
||||||
if device_index < 0:
|
if device_index < 0:
|
||||||
QMessageBox.warning(self, "错误", "请先选择一个相机设备!")
|
QMessageBox.warning(self, "错误", "请先选择一个有效的相机设备!")
|
||||||
return
|
return
|
||||||
|
|
||||||
success = self.camera_manager.open_device(device_index)
|
self.open_button.setEnabled(False)
|
||||||
|
self.open_button.setText("打开中...")
|
||||||
|
|
||||||
if success:
|
try:
|
||||||
# 获取相机参数并更新UI
|
success = self.camera_manager.open_device(device_index)
|
||||||
self.get_camera_params()
|
if success:
|
||||||
|
self.get_camera_params()
|
||||||
# 更新控件状态
|
self.signal_camera_connection.emit(True, "")
|
||||||
|
else:
|
||||||
|
self.signal_camera_connection.emit(False, "打开相机失败")
|
||||||
|
QMessageBox.warning(self, "错误", "打开相机失败")
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.critical(self, "错误", f"打开相机时发生异常: {str(e)}")
|
||||||
|
finally:
|
||||||
|
self.open_button.setText("打开相机")
|
||||||
self.update_controls()
|
self.update_controls()
|
||||||
|
|
||||||
# 发送连接信号
|
|
||||||
self.signal_camera_connection.emit(True, "")
|
|
||||||
else:
|
|
||||||
# 发送连接失败信号
|
|
||||||
self.signal_camera_connection.emit(False, "打开相机失败")
|
|
||||||
|
|
||||||
def close_camera(self):
|
def close_camera(self):
|
||||||
"""关闭相机"""
|
"""关闭相机"""
|
||||||
if not self.camera_manager.isOpen:
|
if not self.camera_manager.isOpen:
|
||||||
return
|
return
|
||||||
|
|
||||||
success = self.camera_manager.close_device()
|
self.camera_manager.close_device()
|
||||||
|
self.signal_camera_connection.emit(False, "")
|
||||||
# 更新控件状态
|
|
||||||
self.update_controls()
|
self.update_controls()
|
||||||
|
|
||||||
# 发送连接信号
|
|
||||||
if success:
|
|
||||||
self.signal_camera_connection.emit(False, "")
|
|
||||||
else:
|
|
||||||
self.signal_camera_connection.emit(False, "关闭相机出错")
|
|
||||||
|
|
||||||
def test_camera(self):
|
def test_camera(self):
|
||||||
"""测试相机(在预览窗口显示图像)"""
|
"""测试相机(在预览窗口显示图像)"""
|
||||||
if not self.camera_manager.isOpen:
|
if not self.camera_manager.isOpen:
|
||||||
QMessageBox.warning(self, "错误", "请先打开相机!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.camera_manager.isGrabbing:
|
if self.camera_manager.isGrabbing:
|
||||||
# 停止预览
|
|
||||||
self.camera_manager.stop_grabbing()
|
self.camera_manager.stop_grabbing()
|
||||||
self.test_button.setText("开始预览")
|
self.test_button.setText("开始预览")
|
||||||
self.update_controls()
|
|
||||||
else:
|
else:
|
||||||
# 获取预览窗口句柄
|
|
||||||
try:
|
try:
|
||||||
# 尝试使用PySide6方式获取窗口句柄
|
|
||||||
window_id = int(self.preview_frame.winId())
|
window_id = int(self.preview_frame.winId())
|
||||||
except:
|
if self.camera_manager.start_grabbing(window_id):
|
||||||
try:
|
self.test_button.setText("停止预览")
|
||||||
# 尝试使用PyQt5方式获取窗口句柄
|
except Exception as e:
|
||||||
window_id = self.preview_frame.winId().__int__()
|
QMessageBox.warning(self, "错误", f"开始预览失败: {e}")
|
||||||
except:
|
|
||||||
# 其他情况
|
self.update_controls()
|
||||||
window_id = int(self.preview_frame.winId())
|
|
||||||
|
|
||||||
# 开始预览
|
|
||||||
success = self.camera_manager.start_grabbing(window_id)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
self.test_button.setText("停止预览")
|
|
||||||
else:
|
|
||||||
QMessageBox.warning(self, "错误", "开始预览失败!")
|
|
||||||
|
|
||||||
# 更新控件状态
|
|
||||||
self.update_controls()
|
|
||||||
|
|
||||||
def update_exposure_value(self, value):
|
def update_exposure_value(self, value):
|
||||||
"""更新曝光值显示"""
|
"""更新曝光值显示"""
|
||||||
# 将滑块值转换为实际曝光值(对数映射)
|
|
||||||
min_log = log10(self.exposure_min)
|
min_log = log10(self.exposure_min)
|
||||||
max_log = log10(self.exposure_max)
|
max_log = log10(self.exposure_max)
|
||||||
log_range = max_log - min_log
|
log_range = max_log - min_log
|
||||||
|
|
||||||
log_value = min_log + (value / 100.0) * log_range
|
log_value = min_log + (value / 100.0) * log_range
|
||||||
actual_value = 10 ** log_value
|
actual_value = 10 ** log_value
|
||||||
|
|
||||||
# 更新显示
|
|
||||||
self.exposure_value.setText(f"{actual_value:.1f} μs")
|
self.exposure_value.setText(f"{actual_value:.1f} μs")
|
||||||
|
|
||||||
def update_gain_value(self, value):
|
def update_gain_value(self, value):
|
||||||
"""更新增益值显示"""
|
"""更新增益值显示"""
|
||||||
# 将滑块值转换为实际增益值
|
|
||||||
actual_value = self.gain_min + (value / 100.0) * (self.gain_max - self.gain_min)
|
actual_value = self.gain_min + (value / 100.0) * (self.gain_max - self.gain_min)
|
||||||
|
|
||||||
# 更新显示
|
|
||||||
self.gain_value.setText(f"{actual_value:.1f} dB")
|
self.gain_value.setText(f"{actual_value:.1f} dB")
|
||||||
|
|
||||||
def update_frame_rate_value(self, value):
|
def update_frame_rate_value(self, value):
|
||||||
"""更新帧率值显示"""
|
"""更新帧率值显示"""
|
||||||
# 将滑块值转换为实际帧率值
|
|
||||||
actual_value = self.frame_rate_min + (value / 100.0) * (self.frame_rate_max - self.frame_rate_min)
|
actual_value = self.frame_rate_min + (value / 100.0) * (self.frame_rate_max - self.frame_rate_min)
|
||||||
|
|
||||||
# 更新显示
|
|
||||||
self.framerate_value.setText(f"{actual_value:.1f} fps")
|
self.framerate_value.setText(f"{actual_value:.1f} fps")
|
||||||
|
|
||||||
def get_camera_params(self):
|
def get_camera_params(self):
|
||||||
"""获取相机参数"""
|
"""获取相机参数"""
|
||||||
if not self.camera_manager.isOpen:
|
if not self.camera_manager.isOpen:
|
||||||
QMessageBox.warning(self, "错误", "请先打开相机!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 获取参数
|
|
||||||
params = self.camera_manager.get_parameters()
|
params = self.camera_manager.get_parameters()
|
||||||
if not params:
|
if not params:
|
||||||
QMessageBox.warning(self, "错误", "获取相机参数失败!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
exposure_time, gain, frame_rate = params
|
exposure_time, gain, frame_rate = params
|
||||||
|
|
||||||
# 更新滑块值
|
min_log_exp = log10(self.exposure_min)
|
||||||
# 曝光时间(对数映射)
|
max_log_exp = log10(self.exposure_max)
|
||||||
min_log = log10(self.exposure_min)
|
self.exposure_slider.setValue(int(((log10(exposure_time) - min_log_exp) / (max_log_exp - min_log_exp)) * 100))
|
||||||
max_log = log10(self.exposure_max)
|
|
||||||
log_range = max_log - min_log
|
|
||||||
log_value = log10(exposure_time)
|
|
||||||
slider_value = int(((log_value - min_log) / log_range) * 100)
|
|
||||||
self.exposure_slider.setValue(slider_value)
|
|
||||||
|
|
||||||
# 增益
|
self.gain_slider.setValue(int(((gain - self.gain_min) / (self.gain_max - self.gain_min)) * 100))
|
||||||
slider_value = int(((gain - self.gain_min) / (self.gain_max - self.gain_min)) * 100)
|
self.framerate_slider.setValue(int(((frame_rate - self.frame_rate_min) / (self.frame_rate_max - self.frame_rate_min)) * 100))
|
||||||
self.gain_slider.setValue(slider_value)
|
|
||||||
|
|
||||||
# 帧率
|
|
||||||
slider_value = int(((frame_rate - self.frame_rate_min) / (self.frame_rate_max - self.frame_rate_min)) * 100)
|
|
||||||
self.framerate_slider.setValue(slider_value)
|
|
||||||
|
|
||||||
# 发送参数变化信号
|
|
||||||
self.signal_camera_params_changed.emit(exposure_time, gain, frame_rate)
|
self.signal_camera_params_changed.emit(exposure_time, gain, frame_rate)
|
||||||
|
|
||||||
def set_camera_params(self):
|
def set_camera_params(self):
|
||||||
"""设置相机参数"""
|
"""设置相机参数"""
|
||||||
if not self.camera_manager.isOpen:
|
if not self.camera_manager.isOpen:
|
||||||
QMessageBox.warning(self, "错误", "请先打开相机!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 从滑块获取参数值
|
|
||||||
# 曝光时间(对数映射)
|
|
||||||
min_log = log10(self.exposure_min)
|
min_log = log10(self.exposure_min)
|
||||||
max_log = log10(self.exposure_max)
|
max_log = log10(self.exposure_max)
|
||||||
log_range = max_log - min_log
|
log_range = max_log - min_log
|
||||||
log_value = min_log + (self.exposure_slider.value() / 100.0) * log_range
|
log_value = min_log + (self.exposure_slider.value() / 100.0) * log_range
|
||||||
exposure_time = 10 ** log_value
|
exposure_time = 10 ** log_value
|
||||||
|
|
||||||
# 增益
|
|
||||||
gain = self.gain_min + (self.gain_slider.value() / 100.0) * (self.gain_max - self.gain_min)
|
gain = self.gain_min + (self.gain_slider.value() / 100.0) * (self.gain_max - self.gain_min)
|
||||||
|
|
||||||
# 帧率
|
|
||||||
frame_rate = self.frame_rate_min + (self.framerate_slider.value() / 100.0) * (self.frame_rate_max - self.frame_rate_min)
|
frame_rate = self.frame_rate_min + (self.framerate_slider.value() / 100.0) * (self.frame_rate_max - self.frame_rate_min)
|
||||||
|
|
||||||
# 设置参数
|
self.camera_manager.set_parameters(frame_rate, exposure_time, gain)
|
||||||
success = self.camera_manager.set_parameters(frame_rate, exposure_time, gain)
|
self.signal_camera_params_changed.emit(exposure_time, gain, frame_rate)
|
||||||
|
|
||||||
if success:
|
|
||||||
QMessageBox.information(self, "成功", "相机参数设置成功!")
|
|
||||||
|
|
||||||
# 发送参数变化信号
|
|
||||||
self.signal_camera_params_changed.emit(exposure_time, gain, frame_rate)
|
|
||||||
else:
|
|
||||||
QMessageBox.warning(self, "错误", "相机参数设置失败!")
|
|
||||||
|
|
||||||
def save_camera_params(self):
|
def save_camera_params(self):
|
||||||
"""保存相机参数到配置文件"""
|
"""保存相机参数到配置文件"""
|
||||||
if not self.camera_manager.isOpen:
|
if not self.camera_manager.isOpen:
|
||||||
QMessageBox.warning(self, "错误", "请先打开相机!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 获取当前参数
|
|
||||||
exposure = self.exposure_slider.value()
|
exposure = self.exposure_slider.value()
|
||||||
gain = self.gain_slider.value()
|
gain = self.gain_slider.value()
|
||||||
frame_rate = self.framerate_slider.value()
|
frame_rate = self.framerate_slider.value()
|
||||||
|
|
||||||
# 保存到配置文件
|
if self.camera_manager.save_params_to_config(exposure, gain, frame_rate):
|
||||||
success = self.camera_manager.save_params_to_config(exposure, gain, frame_rate)
|
QMessageBox.information(self, "成功", "相机参数已保存")
|
||||||
|
self.settings_changed.emit()
|
||||||
if success:
|
|
||||||
QMessageBox.information(self, "成功", "相机参数已保存到配置文件")
|
|
||||||
self.settings_changed.emit() # 发送设置变更信号
|
|
||||||
logging.info(f"相机参数已保存: 曝光={exposure}μs, 增益={gain}dB, 帧率={frame_rate}fps")
|
|
||||||
else:
|
else:
|
||||||
QMessageBox.critical(self, "错误", "保存相机参数失败")
|
QMessageBox.critical(self, "错误", "保存相机参数失败")
|
||||||
logging.error("保存相机参数失败")
|
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
"""窗口关闭事件"""
|
"""窗口关闭事件"""
|
||||||
# 确保关闭相机
|
|
||||||
if self.camera_manager.isOpen:
|
if self.camera_manager.isOpen:
|
||||||
self.camera_manager.close_device()
|
self.camera_manager.close_device()
|
||||||
|
super().closeEvent(event)
|
||||||
# 处理事件
|
|
||||||
super().closeEvent(event)
|
|
||||||
|
|||||||
@ -34,9 +34,8 @@ import time
|
|||||||
|
|
||||||
# 导入UI
|
# 导入UI
|
||||||
from ui.main_window_ui import MainWindowUI
|
from ui.main_window_ui import MainWindowUI
|
||||||
# 导入相机显示组件和设置组件
|
# 导入相机显示组件
|
||||||
from widgets.camera_display_widget import CameraDisplayWidget
|
from widgets.camera_display_widget import CameraDisplayWidget
|
||||||
from widgets.camera_settings_widget import CameraSettingsWidget
|
|
||||||
|
|
||||||
# 导入检验配置管理器
|
# 导入检验配置管理器
|
||||||
from utils.inspection_config_manager import InspectionConfigManager
|
from utils.inspection_config_manager import InspectionConfigManager
|
||||||
|
|||||||
76
widgets/refresh_devices_fix.py
Normal file
76
widgets/refresh_devices_fix.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
"""
|
||||||
|
刷新相机设备按钮修复工具
|
||||||
|
|
||||||
|
此文件包含修复相机设备刷新按钮的工具函数
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from PySide6.QtWidgets import QPushButton
|
||||||
|
|
||||||
|
def fix_camera_refresh_button(settings_widget):
|
||||||
|
"""
|
||||||
|
修复相机设置中的刷新设备按钮
|
||||||
|
|
||||||
|
Args:
|
||||||
|
settings_widget: 设置窗口实例
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功修复
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logging.info("尝试修复相机刷新设备按钮...")
|
||||||
|
|
||||||
|
# 检查是否存在相机设置组件
|
||||||
|
if not hasattr(settings_widget, 'camera_settings'):
|
||||||
|
logging.error("设置窗口中没有camera_settings属性")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查是否存在刷新按钮
|
||||||
|
if hasattr(settings_widget, 'refresh_button'):
|
||||||
|
refresh_button = settings_widget.refresh_button
|
||||||
|
logging.info(f"在settings_widget中找到刷新按钮: {refresh_button}")
|
||||||
|
else:
|
||||||
|
# 尝试查找刷新按钮
|
||||||
|
refresh_button = None
|
||||||
|
# 方法1: 直接在camera_tab中查找
|
||||||
|
if hasattr(settings_widget, 'camera_tab'):
|
||||||
|
for child in settings_widget.camera_tab.findChildren(QPushButton):
|
||||||
|
if child.text() == "刷新设备":
|
||||||
|
refresh_button = child
|
||||||
|
logging.info(f"在camera_tab中找到刷新按钮: {refresh_button}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# 方法2: 在camera_settings中查找
|
||||||
|
if refresh_button is None and hasattr(settings_widget.camera_settings, 'refresh_button'):
|
||||||
|
refresh_button = settings_widget.camera_settings.refresh_button
|
||||||
|
logging.info(f"在camera_settings中找到刷新按钮: {refresh_button}")
|
||||||
|
|
||||||
|
# 如果找到了刷新按钮,则绑定事件
|
||||||
|
if refresh_button:
|
||||||
|
# 断开所有现有连接
|
||||||
|
try:
|
||||||
|
refresh_button.clicked.disconnect()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 连接到refresh_devices方法
|
||||||
|
refresh_button.clicked.connect(settings_widget.camera_settings.refresh_devices)
|
||||||
|
logging.info("成功绑定刷新按钮到refresh_devices方法")
|
||||||
|
|
||||||
|
# 测试调用一次
|
||||||
|
try:
|
||||||
|
settings_widget.camera_settings.refresh_devices()
|
||||||
|
logging.info("已手动调用refresh_devices方法初始化设备列表")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"调用refresh_devices失败: {str(e)}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error("未找到刷新设备按钮")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"修复相机刷新按钮时发生错误: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
logging.error(traceback.format_exc())
|
||||||
|
return False
|
||||||
@ -1,57 +0,0 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
try:
|
|
||||||
from PySide6.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QDialogButtonBox
|
|
||||||
from PySide6.QtCore import Qt
|
|
||||||
except ImportError:
|
|
||||||
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QDialogButtonBox
|
|
||||||
from PyQt5.QtCore import Qt
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsDialog(QDialog):
|
|
||||||
"""设置对话框,用于显示和管理各种设置页面"""
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
|
|
||||||
# 设置对话框标题和大小
|
|
||||||
self.setWindowTitle("系统设置")
|
|
||||||
self.resize(800, 600)
|
|
||||||
|
|
||||||
# 创建布局
|
|
||||||
self.layout = QVBoxLayout(self)
|
|
||||||
|
|
||||||
# 创建选项卡控件
|
|
||||||
self.tab_widget = QTabWidget()
|
|
||||||
self.layout.addWidget(self.tab_widget)
|
|
||||||
|
|
||||||
# 创建按钮盒
|
|
||||||
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
|
||||||
self.button_box.accepted.connect(self.accept)
|
|
||||||
self.button_box.rejected.connect(self.reject)
|
|
||||||
self.layout.addWidget(self.button_box)
|
|
||||||
|
|
||||||
# 设置窗口模态
|
|
||||||
self.setModal(True)
|
|
||||||
|
|
||||||
logging.info("设置对话框已创建")
|
|
||||||
|
|
||||||
def add_settings_page(self, widget, title):
|
|
||||||
"""添加设置页面
|
|
||||||
|
|
||||||
Args:
|
|
||||||
widget: 设置页面部件
|
|
||||||
title: 页面标题
|
|
||||||
"""
|
|
||||||
self.tab_widget.addTab(widget, title)
|
|
||||||
logging.info(f"已添加设置页面: {title}")
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
"""确认按钮处理"""
|
|
||||||
logging.info("设置已保存")
|
|
||||||
super().accept()
|
|
||||||
|
|
||||||
def reject(self):
|
|
||||||
"""取消按钮处理"""
|
|
||||||
logging.info("设置已取消")
|
|
||||||
super().reject()
|
|
||||||
@ -12,6 +12,7 @@ from utils.config_loader import ConfigLoader
|
|||||||
from utils.app_mode import AppMode
|
from utils.app_mode import AppMode
|
||||||
from widgets.camera_settings_widget import CameraSettingsWidget
|
from widgets.camera_settings_widget import CameraSettingsWidget
|
||||||
from widgets.serial_settings_widget import SerialSettingsWidget
|
from widgets.serial_settings_widget import SerialSettingsWidget
|
||||||
|
from ui.electricity_settings_ui import ElectricitySettingsUI
|
||||||
|
|
||||||
class SettingsWidget(SettingsUI):
|
class SettingsWidget(SettingsUI):
|
||||||
# 定义信号
|
# 定义信号
|
||||||
@ -24,13 +25,91 @@ class SettingsWidget(SettingsUI):
|
|||||||
|
|
||||||
logging.info("正在初始化SettingsWidget")
|
logging.info("正在初始化SettingsWidget")
|
||||||
|
|
||||||
|
# 先检查UI中的相机下拉框
|
||||||
|
if hasattr(self, 'camera_combo') and self.camera_combo is not None:
|
||||||
|
logging.info(f"相机下拉框状态检查: 可见={self.camera_combo.isVisible()}, "
|
||||||
|
f"尺寸={self.camera_combo.size().width()}x{self.camera_combo.size().height()}, "
|
||||||
|
f"包含项={self.camera_combo.count()}")
|
||||||
|
else:
|
||||||
|
logging.error("无法找到相机下拉框(camera_combo)!")
|
||||||
|
|
||||||
|
# 检查刷新按钮
|
||||||
|
if hasattr(self, 'refresh_button') and self.refresh_button is not None:
|
||||||
|
logging.info(f"刷新按钮状态检查: 可见={self.refresh_button.isVisible()}, "
|
||||||
|
f"尺寸={self.refresh_button.size().width()}x{self.refresh_button.size().height()}")
|
||||||
|
else:
|
||||||
|
logging.error("无法找到刷新按钮(refresh_button)!")
|
||||||
|
|
||||||
# 创建子设置控制器
|
# 创建子设置控制器
|
||||||
self.camera_settings = CameraSettingsWidget(self)
|
try:
|
||||||
|
# 先添加一个测试项到下拉框
|
||||||
|
if hasattr(self, 'camera_combo'):
|
||||||
|
self.camera_combo.clear()
|
||||||
|
self.camera_combo.addItem("测试项 - 初始化前")
|
||||||
|
logging.info(f"已添加测试项到下拉框,当前项数={self.camera_combo.count()}")
|
||||||
|
|
||||||
|
self.camera_settings = CameraSettingsWidget(self)
|
||||||
|
logging.info("相机设置组件创建成功")
|
||||||
|
|
||||||
|
# 确保相机设置组件正确初始化信号和槽(手动调用一次connect_signals)
|
||||||
|
if hasattr(self.camera_settings, 'connect_signals'):
|
||||||
|
logging.info("手动调用相机设置控制器的connect_signals方法")
|
||||||
|
self.camera_settings.connect_signals()
|
||||||
|
|
||||||
|
# 添加后处理:直接给刷新按钮添加事件处理
|
||||||
|
if hasattr(self, 'refresh_button'):
|
||||||
|
logging.info("手动绑定SettingsWidget中的刷新按钮点击事件")
|
||||||
|
try:
|
||||||
|
self.refresh_button.clicked.disconnect() # 断开所有现有连接
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"断开刷新按钮现有连接时出错: {e}")
|
||||||
|
|
||||||
|
self.refresh_button.clicked.connect(self.camera_settings.refresh_devices)
|
||||||
|
|
||||||
|
# 立即调用一次刷新方法
|
||||||
|
self.camera_settings.refresh_devices()
|
||||||
|
logging.info("已刷新相机设备列表")
|
||||||
|
|
||||||
|
# 再次检查相机下拉框状态
|
||||||
|
if hasattr(self, 'camera_combo'):
|
||||||
|
logging.info(f"刷新后相机下拉框状态: 项目数={self.camera_combo.count()}, "
|
||||||
|
f"当前文本={self.camera_combo.currentText() if self.camera_combo.count() > 0 else 'None'}")
|
||||||
|
|
||||||
|
# 尝试手动向下拉框添加一项
|
||||||
|
self.camera_combo.addItem("测试项 - 手动添加")
|
||||||
|
logging.info(f"手动添加后下拉框状态: 项目数={self.camera_combo.count()}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"初始化相机设置组件失败: {e}")
|
||||||
|
|
||||||
self.serial_settings = SerialSettingsWidget(self)
|
self.serial_settings = SerialSettingsWidget(self)
|
||||||
self.inspection_settings = InspectionSettingsWidget(self)
|
self.inspection_settings = InspectionSettingsWidget(self)
|
||||||
self.pallet_type_settings = PalletTypeSettingsWidget(self)
|
self.pallet_type_settings = PalletTypeSettingsWidget(self)
|
||||||
self.plc_settings = PLCSettingsWidget(self)
|
self.plc_settings = PLCSettingsWidget(self)
|
||||||
|
|
||||||
|
# 创建电量监控设置组件
|
||||||
|
try:
|
||||||
|
self.electricity_settings = ElectricitySettingsUI(self)
|
||||||
|
logging.info("电量监控设置组件创建成功")
|
||||||
|
|
||||||
|
# 移除临时占位符标签并添加电量监控设置部件
|
||||||
|
if hasattr(self, 'electricity_placeholder'):
|
||||||
|
logging.info("移除电量监控临时占位符")
|
||||||
|
self.electricity_layout.removeWidget(self.electricity_placeholder)
|
||||||
|
self.electricity_placeholder.hide()
|
||||||
|
self.electricity_placeholder.deleteLater()
|
||||||
|
else:
|
||||||
|
logging.warning("未找到电量监控临时占位符标签")
|
||||||
|
|
||||||
|
# 检查布局是否可用
|
||||||
|
if hasattr(self, 'electricity_layout'):
|
||||||
|
logging.info("添加电量监控设置部件到布局")
|
||||||
|
self.electricity_layout.addWidget(self.electricity_settings)
|
||||||
|
else:
|
||||||
|
logging.error("无法找到electricity_layout布局")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"初始化电量监控设置组件失败: {e}")
|
||||||
|
|
||||||
# 移除临时占位符标签并添加检验设置部件
|
# 移除临时占位符标签并添加检验设置部件
|
||||||
if hasattr(self, 'inspection_placeholder'):
|
if hasattr(self, 'inspection_placeholder'):
|
||||||
logging.info("移除临时占位符")
|
logging.info("移除临时占位符")
|
||||||
@ -84,12 +163,43 @@ class SettingsWidget(SettingsUI):
|
|||||||
def connect_signals(self):
|
def connect_signals(self):
|
||||||
"""连接信号和槽"""
|
"""连接信号和槽"""
|
||||||
# 连接子设置控制器的信号
|
# 连接子设置控制器的信号
|
||||||
self.camera_settings.settings_changed.connect(self.on_settings_changed)
|
if hasattr(self, 'camera_settings'):
|
||||||
|
try:
|
||||||
|
self.camera_settings.settings_changed.connect(self.on_settings_changed)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"连接相机设置信号时出错: {e}")
|
||||||
|
|
||||||
self.serial_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.inspection_settings.settings_changed.connect(self.on_settings_changed)
|
||||||
self.pallet_type_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.plc_settings.settings_changed.connect(self.on_settings_changed)
|
||||||
|
|
||||||
|
# 连接电量监控设置信号
|
||||||
|
if hasattr(self, 'electricity_settings'):
|
||||||
|
try:
|
||||||
|
self.electricity_settings.settings_changed.connect(self.on_settings_changed)
|
||||||
|
logging.info("已连接电量监控设置信号")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"连接电量监控设置信号时出错: {e}")
|
||||||
|
|
||||||
|
# 直接连接相机标签页中的刷新按钮
|
||||||
|
try:
|
||||||
|
if hasattr(self, 'camera_tab') and hasattr(self, 'refresh_button') and hasattr(self, 'camera_settings'):
|
||||||
|
logging.info("在SettingsWidget中直接连接刷新按钮")
|
||||||
|
try:
|
||||||
|
# 断开可能存在的连接
|
||||||
|
self.refresh_button.clicked.disconnect()
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"断开刷新按钮现有连接时出错: {e}")
|
||||||
|
|
||||||
|
# 连接到相机设置控件的刷新方法
|
||||||
|
self.refresh_button.clicked.connect(self.camera_settings.refresh_devices)
|
||||||
|
|
||||||
|
# 立即调用一次刷新方法
|
||||||
|
self.camera_settings.refresh_devices()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"连接刷新按钮时出错: {e}")
|
||||||
|
|
||||||
# 数据库类型选择
|
# 数据库类型选择
|
||||||
self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state)
|
self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state)
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,113 @@ class SettingsWindow(QDialog):
|
|||||||
self.settings_widget = SettingsWidget(self)
|
self.settings_widget = SettingsWidget(self)
|
||||||
main_layout.addWidget(self.settings_widget)
|
main_layout.addWidget(self.settings_widget)
|
||||||
|
|
||||||
|
# 应用相机刷新按钮修复
|
||||||
|
try:
|
||||||
|
# 先尝试直接找到刷新按钮并添加事件处理
|
||||||
|
logging.info("尝试直接查找刷新按钮并添加事件处理...")
|
||||||
|
from PySide6.QtWidgets import QPushButton
|
||||||
|
|
||||||
|
# 在整个UI层次中查找刷新设备按钮
|
||||||
|
refresh_buttons = []
|
||||||
|
for widget in self.findChildren(QPushButton):
|
||||||
|
if widget.text() == "刷新设备":
|
||||||
|
refresh_buttons.append(widget)
|
||||||
|
|
||||||
|
if refresh_buttons:
|
||||||
|
logging.info(f"找到 {len(refresh_buttons)} 个刷新设备按钮")
|
||||||
|
for i, button in enumerate(refresh_buttons):
|
||||||
|
try:
|
||||||
|
# 断开现有连接
|
||||||
|
button.clicked.disconnect()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 连接到相机设置的刷新方法
|
||||||
|
if hasattr(self.settings_widget, 'camera_settings') and hasattr(self.settings_widget.camera_settings, 'refresh_devices'):
|
||||||
|
button.clicked.connect(self.settings_widget.camera_settings.refresh_devices)
|
||||||
|
logging.info(f"已将刷新按钮 #{i+1} 连接到refresh_devices方法")
|
||||||
|
|
||||||
|
# 尝试调用一次
|
||||||
|
self.settings_widget.camera_settings.refresh_devices()
|
||||||
|
logging.info("已手动调用refresh_devices方法初始化设备列表")
|
||||||
|
|
||||||
|
# 使用导入的修复模块作为备选方案
|
||||||
|
try:
|
||||||
|
# 使用相对导入,更可靠
|
||||||
|
from . import refresh_devices_fix
|
||||||
|
refresh_devices_fix.fix_camera_refresh_button(self.settings_widget)
|
||||||
|
logging.info("已应用相机刷新按钮修复(通过相对导入)")
|
||||||
|
except ImportError:
|
||||||
|
# 如果相对导入失败,尝试绝对导入
|
||||||
|
try:
|
||||||
|
import refresh_devices_fix
|
||||||
|
refresh_devices_fix.fix_camera_refresh_button(self.settings_widget)
|
||||||
|
logging.info("已应用相机刷新按钮修复(通过绝对导入)")
|
||||||
|
except ImportError:
|
||||||
|
# 如果绝对导入也失败,直接内联实现修复逻辑
|
||||||
|
logging.warning("导入refresh_devices_fix失败,使用内联修复")
|
||||||
|
self._fix_camera_refresh_button()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"应用相机刷新按钮修复失败: {str(e)}")
|
||||||
|
|
||||||
|
def _fix_camera_refresh_button(self):
|
||||||
|
"""内联实现的刷新按钮修复逻辑,用于导入模块失败的情况"""
|
||||||
|
try:
|
||||||
|
logging.info("使用内联方法修复相机刷新按钮...")
|
||||||
|
|
||||||
|
# 获取设置部件
|
||||||
|
settings_widget = self.settings_widget
|
||||||
|
|
||||||
|
# 确保相机设置组件存在
|
||||||
|
if not hasattr(settings_widget, 'camera_settings'):
|
||||||
|
logging.error("设置窗口中没有camera_settings属性")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 查找刷新按钮
|
||||||
|
refresh_button = None
|
||||||
|
|
||||||
|
# 方法1: 在settings_widget上查找
|
||||||
|
if hasattr(settings_widget, 'refresh_button'):
|
||||||
|
refresh_button = settings_widget.refresh_button
|
||||||
|
logging.info("在settings_widget中找到刷新按钮")
|
||||||
|
# 方法2: 在camera_tab中查找
|
||||||
|
elif hasattr(settings_widget, 'camera_tab'):
|
||||||
|
from PySide6.QtWidgets import QPushButton
|
||||||
|
for child in settings_widget.camera_tab.findChildren(QPushButton):
|
||||||
|
if child.text() == "刷新设备":
|
||||||
|
refresh_button = child
|
||||||
|
logging.info("在camera_tab中找到刷新按钮")
|
||||||
|
break
|
||||||
|
# 方法3: 在camera_settings中查找
|
||||||
|
elif hasattr(settings_widget.camera_settings, 'refresh_button'):
|
||||||
|
refresh_button = settings_widget.camera_settings.refresh_button
|
||||||
|
logging.info("在camera_settings中找到刷新按钮")
|
||||||
|
|
||||||
|
# 如果找到按钮,则绑定事件
|
||||||
|
if refresh_button:
|
||||||
|
from PySide6.QtCore import QObject
|
||||||
|
if isinstance(refresh_button, QObject):
|
||||||
|
try:
|
||||||
|
# 断开现有连接
|
||||||
|
refresh_button.clicked.disconnect()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 连接到刷新方法
|
||||||
|
refresh_button.clicked.connect(settings_widget.camera_settings.refresh_devices)
|
||||||
|
logging.info("成功绑定刷新按钮到refresh_devices方法")
|
||||||
|
|
||||||
|
# 手动调用一次
|
||||||
|
settings_widget.camera_settings.refresh_devices()
|
||||||
|
logging.info("已手动调用refresh_devices初始化设备列表")
|
||||||
|
else:
|
||||||
|
logging.error(f"刷新按钮不是QObject: {type(refresh_button)}")
|
||||||
|
else:
|
||||||
|
logging.error("未找到刷新设备按钮")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"内联修复相机刷新按钮时发生错误: {str(e)}")
|
||||||
|
|
||||||
# 添加串口设置到标签页
|
# 添加串口设置到标签页
|
||||||
self.serial_settings = SerialSettingsWidget(self)
|
self.serial_settings = SerialSettingsWidget(self)
|
||||||
self.settings_widget.tab_widget.addTab(self.serial_settings, "串口设置")
|
self.settings_widget.tab_widget.addTab(self.serial_settings, "串口设置")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user