# -*- coding: utf-8 -*- """ 相机控制界面 本模块提供了一个基于Tkinter的相机控制界面,用于调节相机的曝光时间、增益等参数。 """ import tkinter as tk from tkinter import ttk import threading import time from camera import Camera class CameraControlPanel: """ 相机控制面板类 """ def __init__(self, root, camera): """ 初始化相机控制面板 Args: root: 父窗口 camera: 相机实例 """ self.root = root self.camera = camera self.root.title("相机控制面板") self.root.geometry("500x400") self.root.resizable(True, True) # 创建主框架 self.main_frame = ttk.Frame(self.root, padding="10") self.main_frame.pack(fill=tk.BOTH, expand=True) # 相机状态 self.status_var = tk.StringVar(value="未初始化") # 曝光时间变量 self.exp_var = tk.DoubleVar(value=5000.0) self.exp_var.trace("w", self.on_exp_change) # 增益变量 self.gain_var = tk.DoubleVar(value=0.0) self.gain_var.trace("w", self.on_gain_change) # 帧率变量 self.fps_var = tk.DoubleVar(value=30.0) self.fps_var.trace("w", self.on_fps_change) # 状态标签 self.create_status_section() # 相机控制 self.create_control_section() # 参数调节 self.create_param_section() # 日志区域 self.create_log_section() # 初始化相机 self.init_camera() def create_status_section(self): """ 创建状态显示区域 """ status_frame = ttk.LabelFrame(self.main_frame, text="相机状态", padding="10") status_frame.pack(fill=tk.X, pady=5) status_label = ttk.Label(status_frame, textvariable=self.status_var, font=("Arial", 12, "bold")) status_label.pack(anchor=tk.W) def create_control_section(self): """ 创建相机控制区域 """ control_frame = ttk.LabelFrame(self.main_frame, text="相机控制", padding="10") control_frame.pack(fill=tk.X, pady=5) # 按钮容器 button_frame = ttk.Frame(control_frame) button_frame.pack(fill=tk.X) # 初始化按钮 self.init_button = ttk.Button(button_frame, text="初始化相机", command=self.init_camera) self.init_button.pack(side=tk.LEFT, padx=5) # 打开按钮 self.open_button = ttk.Button(button_frame, text="打开相机", command=self.open_camera, state=tk.DISABLED) self.open_button.pack(side=tk.LEFT, padx=5) # 开始取流按钮 self.start_button = ttk.Button(button_frame, text="开始取流", command=self.start_grabbing, state=tk.DISABLED) self.start_button.pack(side=tk.LEFT, padx=5) # 停止取流按钮 self.stop_button = ttk.Button(button_frame, text="停止取流", command=self.stop_grabbing, state=tk.DISABLED) self.stop_button.pack(side=tk.LEFT, padx=5) # 关闭按钮 self.close_button = ttk.Button(button_frame, text="关闭相机", command=self.close_camera, state=tk.DISABLED) self.close_button.pack(side=tk.LEFT, padx=5) def create_param_section(self): """ 创建参数调节区域 """ param_frame = ttk.LabelFrame(self.main_frame, text="参数调节", padding="10") param_frame.pack(fill=tk.X, pady=5) # 曝光时间 exp_frame = ttk.Frame(param_frame) exp_frame.pack(fill=tk.X, pady=5) exp_label = ttk.Label(exp_frame, text="曝光时间 (μs):") exp_label.pack(side=tk.LEFT, padx=5) exp_scale = ttk.Scale(exp_frame, from_=100.0, to=50000.0, orient=tk.HORIZONTAL, variable=self.exp_var, length=200) exp_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X) exp_entry = ttk.Entry(exp_frame, textvariable=self.exp_var, width=10) exp_entry.pack(side=tk.LEFT, padx=5) # 增益 gain_frame = ttk.Frame(param_frame) gain_frame.pack(fill=tk.X, pady=5) gain_label = ttk.Label(gain_frame, text="增益 (dB):") gain_label.pack(side=tk.LEFT, padx=5) gain_scale = ttk.Scale(gain_frame, from_=0.0, to=48.0, orient=tk.HORIZONTAL, variable=self.gain_var, length=200) gain_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X) gain_entry = ttk.Entry(gain_frame, textvariable=self.gain_var, width=10) gain_entry.pack(side=tk.LEFT, padx=5) # 帧率 fps_frame = ttk.Frame(param_frame) fps_frame.pack(fill=tk.X, pady=5) fps_label = ttk.Label(fps_frame, text="帧率 (fps):") fps_label.pack(side=tk.LEFT, padx=5) fps_scale = ttk.Scale(fps_frame, from_=1.0, to=60.0, orient=tk.HORIZONTAL, variable=self.fps_var, length=200) fps_scale.pack(side=tk.LEFT, padx=5, expand=True, fill=tk.X) fps_entry = ttk.Entry(fps_frame, textvariable=self.fps_var, width=10) fps_entry.pack(side=tk.LEFT, padx=5) def create_log_section(self): """ 创建日志显示区域 """ log_frame = ttk.LabelFrame(self.main_frame, text="日志", padding="10") log_frame.pack(fill=tk.BOTH, expand=True, pady=5) # 创建文本框 self.log_text = tk.Text(log_frame, height=10, wrap=tk.WORD) self.log_text.pack(fill=tk.BOTH, expand=True) # 添加滚动条 scrollbar = ttk.Scrollbar(self.log_text, command=self.log_text.yview) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.log_text.config(yscrollcommand=scrollbar.set) def log(self, message): """ 添加日志信息 Args: message: 日志消息 """ timestamp = time.strftime("%Y-%m-%d %H:%M:%S") log_message = f"[{timestamp}] {message}\n" self.log_text.insert(tk.END, log_message) self.log_text.see(tk.END) def init_camera(self): """ 初始化相机 """ try: self.log("正在初始化相机...") self.status_var.set("初始化中") # 枚举设备 device_count = self.camera.enum_devices() if device_count == 0: self.log("未找到相机设备") self.status_var.set("未找到设备") return self.log(f"找到 {device_count} 台相机设备") self.status_var.set("就绪") # 启用打开按钮 self.open_button.config(state=tk.NORMAL) self.log("相机初始化成功") except Exception as e: self.log(f"初始化失败: {e}") self.status_var.set("初始化失败") def open_camera(self): """ 打开相机 """ try: self.log("正在打开相机...") self.status_var.set("打开中") # 打开设备(默认使用索引0) ret = self.camera.open_device(0) if ret != 0: self.log(f"打开相机失败,错误码: {ret}") self.status_var.set("打开失败") return self.log("相机打开成功") self.status_var.set("已打开") # 更新参数显示 self.exp_var.set(self.camera.current_exp) self.gain_var.set(self.camera.current_gain) self.fps_var.set(self.camera.current_fps) # 启用控制按钮 self.start_button.config(state=tk.NORMAL) self.close_button.config(state=tk.NORMAL) self.open_button.config(state=tk.DISABLED) except Exception as e: self.log(f"打开相机失败: {e}") self.status_var.set("打开失败") def start_grabbing(self): """ 开始取流 """ try: self.log("正在开始取流...") self.status_var.set("取流中") ret = self.camera.start_grabbing() if ret != 0: self.log(f"开始取流失败,错误码: {ret}") self.status_var.set("取流失败") return self.log("开始取流成功") self.status_var.set("正在取流") # 更新按钮状态 self.start_button.config(state=tk.DISABLED) self.stop_button.config(state=tk.NORMAL) except Exception as e: self.log(f"开始取流失败: {e}") self.status_var.set("取流失败") def stop_grabbing(self): """ 停止取流 """ try: self.log("正在停止取流...") ret = self.camera.stop_grabbing() if ret != 0: self.log(f"停止取流失败,错误码: {ret}") return self.log("停止取流成功") self.status_var.set("已打开") # 更新按钮状态 self.stop_button.config(state=tk.DISABLED) self.start_button.config(state=tk.NORMAL) except Exception as e: self.log(f"停止取流失败: {e}") def close_camera(self): """ 关闭相机 """ try: self.log("正在关闭相机...") self.camera.close_device() self.log("相机关闭成功") self.status_var.set("已关闭") # 更新按钮状态 self.close_button.config(state=tk.DISABLED) self.stop_button.config(state=tk.DISABLED) self.start_button.config(state=tk.DISABLED) self.open_button.config(state=tk.NORMAL) except Exception as e: self.log(f"关闭相机失败: {e}") def on_exp_change(self, *args): """ 曝光时间变化回调 """ if self.camera.is_open: try: exp_value = self.exp_var.get() ret = self.camera.set_exposure_time(exp_value) if ret == 0: self.log(f"曝光时间设置为: {exp_value} μs") except Exception as e: self.log(f"设置曝光时间失败: {e}") def on_gain_change(self, *args): """ 增益变化回调 """ if self.camera.is_open: try: gain_value = self.gain_var.get() ret = self.camera.set_gain(gain_value) if ret == 0: self.log(f"增益设置为: {gain_value} dB") except Exception as e: self.log(f"设置增益失败: {e}") def on_fps_change(self, *args): """ 帧率变化回调 """ if self.camera.is_open: try: fps_value = self.fps_var.get() ret = self.camera.set_frame_rate(fps_value) if ret == 0: self.log(f"帧率设置为: {fps_value} fps") except Exception as e: self.log(f"设置帧率失败: {e}") if __name__ == "__main__": """ 测试相机控制面板 """ import tkinter as tk # 创建根窗口 root = tk.Tk() # 创建相机实例 camera = Camera() # 创建控制面板 app = CameraControlPanel(root, camera) # 运行主循环 try: root.mainloop() finally: # 确保关闭相机 camera.close_device()