From f7dbf223cbb4cb6b9bc214e072f767e6fffaed92 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Oct 2025 15:21:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=87=E9=9B=86=E5=8D=A1bug=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gui_config.py | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/gui_config.py b/gui_config.py index f960c54..315d643 100644 --- a/gui_config.py +++ b/gui_config.py @@ -1,7 +1,9 @@ import tkinter as tk from tkinter import ttk, messagebox, simpledialog +import cv2 from config import config_manager import threading +import serial.tools.list_ports class ConfigGUI: """配置GUI界面""" @@ -49,7 +51,16 @@ class ConfigGUI: basic_frame.pack(fill=tk.X, pady=5) self.create_entry(basic_frame, "name", "配置组名称:") - self.create_entry(basic_frame, "camera_index", "采集卡索引:") + # 采集卡索引:使用下拉+扫描 + cam_row = ttk.Frame(basic_frame) + cam_row.pack(fill=tk.X, pady=3) + ttk.Label(cam_row, text="采集卡索引:", width=15).pack(side=tk.LEFT) + self.camera_index_var = tk.StringVar() + self.camera_index_cb = ttk.Combobox(cam_row, textvariable=self.camera_index_var, width=23, state="readonly") + self.camera_index_cb.pack(side=tk.LEFT, padx=5) + ttk.Button(cam_row, text="扫描采集卡", command=self.scan_cameras).pack(side=tk.LEFT, padx=5) + # 将变量放进config_vars统一管理 + self.config_vars["camera_index"] = self.camera_index_var self.create_entry(basic_frame, "camera_width", "采集宽度:") self.create_entry(basic_frame, "camera_height", "采集高度:") @@ -57,7 +68,17 @@ class ConfigGUI: serial_frame = ttk.LabelFrame(right_frame, text="串口配置", padding="10") serial_frame.pack(fill=tk.X, pady=5) - self.create_entry(serial_frame, "serial_port", "串口:") + # 串口:使用下拉+扫描 + port_row = ttk.Frame(serial_frame) + port_row.pack(fill=tk.X, pady=3) + ttk.Label(port_row, text="串口:", width=15).pack(side=tk.LEFT) + self.serial_port_var = tk.StringVar() + self.serial_port_cb = ttk.Combobox(port_row, textvariable=self.serial_port_var, width=23, state="readonly") + self.serial_port_cb.pack(side=tk.LEFT, padx=5) + ttk.Button(port_row, text="扫描串口", command=self.scan_ports).pack(side=tk.LEFT, padx=5) + # 将变量放进config_vars统一管理 + self.config_vars["serial_port"] = self.serial_port_var + self.create_entry(serial_frame, "serial_baudrate", "波特率:") # 游戏配置 @@ -111,6 +132,15 @@ class ConfigGUI: for key in ['preview_width', 'preview_height', 'preview_columns', 'preview_rows']: if key in display: self.config_vars[f"display_{key}"].set(str(display[key])) + # 初次自动扫描一次采集卡和串口 + try: + self.scan_cameras() + except Exception: + pass + try: + self.scan_ports() + except Exception: + pass def update_group_list(self): """更新配置组列表""" @@ -134,6 +164,68 @@ class ConfigGUI: if not key.startswith('display_'): if key in group: var.set(str(group[key])) + # 确保下拉框列表与当前值一致 + if group and 'camera_index' in group: + # 如果当前索引不在选项里,追加 + values = list(self.camera_index_cb.cget('values')) if self.camera_index_cb.cget('values') else [] + display_value = f"{group['camera_index']}" + if display_value not in values: + values.append(display_value) + self.camera_index_cb['values'] = values + self.camera_index_cb.set(display_value) + + # 确保串口下拉框列表与当前值一致 + if group and 'serial_port' in group: + # 如果当前串口不在选项里,追加 + values = list(self.serial_port_cb.cget('values')) if self.serial_port_cb.cget('values') else [] + port_value = group['serial_port'] + if port_value not in values: + values.append(port_value) + self.serial_port_cb['values'] = values + self.serial_port_cb.set(port_value) + + def scan_cameras(self, max_index: int = 10): + """扫描系统可用的采集卡索引,并填充下拉框""" + found = [] + for idx in range(max_index + 1): + cap = cv2.VideoCapture(idx, cv2.CAP_DSHOW) + if not cap.isOpened(): + # 回退默认后端再试 + cap = cv2.VideoCapture(idx) + if cap.isOpened(): + found.append(str(idx)) + cap.release() + if not found: + found = ["0"] # 至少给一个默认项,避免为空 + self.camera_index_cb['values'] = found + # 若当前无选择,则选择第一项 + if not self.camera_index_var.get() and found: + self.camera_index_cb.set(found[0]) + messagebox.showinfo("扫描完成", f"发现可用采集卡索引: {', '.join(found)}") + + def scan_ports(self): + """扫描系统可用的串口,并填充下拉框""" + found_real = [] + try: + ports = serial.tools.list_ports.comports() + found_real = [port.device for port in ports] + # 按端口名排序 + found_real.sort(key=lambda x: int(x.replace('COM', '')) if x.replace('COM', '').isdigit() else 999) + except Exception as e: + print(f"扫描串口错误: {e}") + + # 如果没有发现实际端口,使用默认端口列表 + if not found_real: + found = ["COM1", "COM2", "COM3", "COM4", "COM5", "COM6"] # 默认给一些常见端口 + messagebox.showwarning("警告", "未发现可用串口设备,已添加常用默认选项") + else: + found = found_real + messagebox.showinfo("扫描完成", f"发现可用串口: {', '.join(found)}") + + self.serial_port_cb['values'] = found + # 若当前无选择,则选择第一项 + if not self.serial_port_var.get() and found: + self.serial_port_cb.set(found[0]) def add_group(self): """添加配置组"""