You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flet程序中关闭cv2窗口?ESC按键无效问题求助

问题根源
  1. OpenCV按键捕获无效:你没有创建OpenCV窗口(cv2.imshow()),cv2.waitKey()只能在OpenCV窗口获得焦点时捕获按键,但你是通过Flet的Image组件展示画面,这方法完全没用。
  2. UI线程被阻塞:摄像头读取的while循环直接跑在Flet主线程里,加上cv2.waitKey(0)的无限等待,导致Flet整个UI卡死,根本没法响应任何用户操作。
  3. 退出逻辑不完整:就算捕获到ESC键,你只调用了cv2.destroyAllWindows(),但没终止循环,摄像头还是会持续读取。
修复后的完整代码
import cv2
import base64
import time
import threading
import flet as ft

cap = cv2.VideoCapture(0)
is_running = True  # 控制摄像头循环的标志

def main(page: ft.Page):
    page.title = "fletCam"
    image_box = ft.Image()
    page.add(image_box)

    def update_images():
        global is_running
        while cap.isOpened() and is_running:
            ret, frame = cap.read()
            if ret:
                # 编码帧为base64格式
                jpg_img = cv2.imencode('.jpg', frame)
                b64_string = base64.b64encode(jpg_img[1]).decode('utf-8')
                image_box.src_base64 = b64_string
                page.update()
                time.sleep(1/30)  # 控制帧率为30帧/秒,平衡流畅度与资源占用
            else:
                break
        # 退出循环后释放摄像头资源
        cap.release()

    # 启动后台线程处理摄像头读取,避免阻塞Flet UI主线程
    threading.Thread(target=update_images, daemon=True).start()

    # 监听键盘事件,处理ESC键退出逻辑
    def on_keyboard(e: ft.KeyboardEvent):
        global is_running
        if e.key == "Escape":
            is_running = False
            page.window_close()  # 关闭Flet应用窗口

    page.on_keyboard_event = on_keyboard

if __name__ == "__main__":
    ft.app(target=main)
关键修复点
  • 改用Flet原生键盘监听:通过page.on_keyboard_event直接捕获ESC键,用is_running标志终止摄像头循环,同时关闭应用窗口。
  • 后台线程隔离摄像头操作:用threading.Thread把摄像头读取逻辑放到后台,保证Flet UI主线程能正常响应所有用户操作。
  • 清理无效代码:删除没用的cv2.waitKey()和cv2.destroyAllWindows(),只保留必要的摄像头资源释放操作。
  • 优化帧率控制:把过高的帧率(115帧/秒)调整为更合理的30帧/秒,既保证画面流畅,又避免浪费系统资源。

内容的提问来源于stack exchange,提问作者Jibin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:57:34