使用Queue更新customtkinter CTkImage时Python程序无响应问题
问题分析与解决方案
核心问题点
- 线程启动错误:启动图像更新线程时,
target=self.read_cam_img()直接调用了函数而非传递引用,导致read_cam_img在主线程执行,其中的time.sleep(25)直接阻塞UI主线程,造成程序无响应。 - UI更新线程违规:customtkinter的UI组件必须在主线程更新,子线程直接修改
CTkLabel图像会引发异常或无响应。 - 队列帧累积问题:原代码未处理队列中的旧帧,导致后续更新显示过时画面;
QR_Daemon中的time.sleep(0.5)会降低帧率,还可能导致队列堆积。 - 单次更新逻辑限制:原
read_cam_img仅执行一次判断,没有循环读取队列,无法实现实时更新。
修正代码示例
1. 修复线程启动逻辑
def launch_qr(self): qr_daemon = QRDaemon(member_list=self.member_section, img_q=self.img_queue) qr_daemon_thread = threading.Thread(target=qr_daemon.main) qr_daemon_thread.daemon = True qr_daemon_thread.start() # 修正:传递函数引用,不在主线程直接执行函数 img_update_thread = threading.Thread(target=self.read_cam_img) img_update_thread.daemon = True img_update_thread.start()
2. 重构图像更新逻辑(子线程取帧,主线程更新UI)
def read_cam_img(self): while True: if not self.img_queue.empty(): # 清空队列旧帧,仅保留最新一帧,避免显示过时画面 while self.img_queue.qsize() > 1: self.img_queue.get() latest_frame = self.img_queue.get() # 通过after方法让主线程执行UI更新,符合customtkinter线程规则 self.img_label.after(0, self._update_ui_frame, latest_frame) # 短时间休眠,降低CPU占用 time.sleep(0.01) def _update_ui_frame(self, frame): # 转换OpenCV灰度帧为PIL Image pil_image = Image.fromarray(frame) # 更新CTkImage并刷新标签 self.image_w.configure(light_image=pil_image, size=(600, 600)) self.img_label.configure(image=self.image_w, text="")
3. 优化QR_Daemon的帧读取逻辑
def main(self): cap = cv2.VideoCapture(0) # 可选:设置摄像头分辨率匹配CTkLabel尺寸 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 600) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600) while True: ret, frame = cap.read() if not ret: break gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 执行二维码读取 self.read_qr_code(gray_frame) # 维护队列:若队列满则移除旧帧,确保存入最新帧 if self.img_q.full(): try: self.img_q.get_nowait() except queue.Empty: pass self.img_q.put(gray_frame) # 用cv2.waitKey控制帧率,替代time.sleep,避免阻塞摄像头读取 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放摄像头资源 cap.release()
额外注意事项
- 初始化
Queue时设置合理的maxsize(比如maxsize=2),避免无限制占用内存。 - 若需显示彩色帧,需将OpenCV的BGR格式转换为RGB格式(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))再转PIL Image。
内容的提问来源于stack exchange,提问作者Ishaan M
相关产品推荐
相关产品推荐

