如何将Python函数输出的列表导入Tkinter GUI并触发对应交互动作
实现方法
核心问题说明
你现在遇到的核心冲突是:OpenCV的视频捕获while True循环和Tkinter的root.mainloop()都是阻塞式逻辑,直接调用会导致其中一个功能卡住无法运行,通用解决方案采用多线程+定时UI刷新实现数据传递。
具体实现步骤
- 第一步:修改手势识别脚本,增加退出控制开关,识别到的结果存入共享变量
- 第二步:在Tkinter脚本中启动独立子线程运行手势识别逻辑,避免阻塞GUI主线程
- 第三步:Tkinter主线程用
after()方法定时读取识别结果,更新对应UI组件
修改后的代码示例
1. 修正FingerCounter.py(手势识别脚本)
import cv2 import time import os import HandTrackingModule as htm # 共享识别结果,初始值设为-1代表未识别到手 recognize_result = -1 # 线程退出开关 run_flag = True def fcf(): global recognize_result, run_flag wCam, hCam = 640, 480 cap = cv2.VideoCapture(0) cap.set(3, wCam) cap.set(4, hCam) folderPath = "FingerImages" myList = os.listdir(folderPath) overlayList = [] for imPath in myList: image = cv2.imread(f'{folderPath}/{imPath}') overlayList.append(image) pTime = 0 detector = htm.handDetector(detectionCon=0.75) tipIds = [4, 8, 12, 16, 20] while run_flag: success, img = cap.read() if not success: break img = detector.findHands(img) lmList = detector.findPosition(img, draw=False) if len(lmList) != 0: fingers = [] # 拇指判断 if lmList[tipIds[0]][1] > lmList[tipIds[0] - 1][1]: fingers.append(1) else: fingers.append(0) # 其余四指判断 for id in range(1, 5): if lmList[tipIds[id]][2] < lmList[tipIds[id] - 2][2]: fingers.append(1) else: fingers.append(0) # 保存识别到的手指总数到共享变量,需要完整fingers列表直接替换即可 recognize_result = fingers.count(1) else: recognize_result = -1 cTime = time.time() fps = 1 / (cTime - pTime) pTime = cTime cv2.putText(img, f'FPS: {int(fps)}', (400, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3) cv2.imshow("Image", img) cv2.waitKey(1) # 退出时释放资源 cap.release() cv2.destroyAllWindows() if __name__ == '__main__': fcf()
2. 修改后的Tkinter GUI脚本
from tkinter import * from PIL import ImageTk, Image import threading # 导入手势识别模块的共享变量和函数 from FingerCounter import fcf, recognize_result, run_flag # UI更新逻辑:根据识别结果更新标签,映射规则可自行修改 def update_ui(): global recognize_result # 示例映射:1=不满意,3=中性,5=满意,可按需调整 if recognize_result == 1: myLabel.config(text="不满意") myLabel2.config(text="") myLabel4.config(text="") elif recognize_result == 3: myLabel.config(text="") myLabel2.config(text="中性") myLabel4.config(text="") elif recognize_result == 5: myLabel.config(text="") myLabel2.config(text="") myLabel4.config(text="满意") else: # 未识别到手清空内容 myLabel.config(text="") myLabel2.config(text="") myLabel4.config(text="") # 每100毫秒刷新一次UI,可根据需求调整间隔 root.after(100, update_ui) # 窗口关闭时的清理逻辑,终止手势识别线程 def on_closing(): global run_flag run_flag = False root.destroy() root = Tk() root.title('Customer Satisfaction Survey') root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) # 绑定窗口关闭事件 root.protocol("WM_DELETE_WINDOW", on_closing) # 图片加载 Img = ImageTk.PhotoImage(Image.open("coo.png")) Img1 = ImageTk.PhotoImage(Image.open("Doo.png")) Img2 = ImageTk.PhotoImage(Image.open("Wave.png")) ImgLabel00 = Label(root, text=" \n \n \n \n\n\n\n\n\n\n\n \n \n \n \n ") ImgLabel00.grid(row=0, column=0, padx=5, pady=5) ImgLabel = Label(image=Img) ImgLabel.grid(row=1, column=2, padx=5, pady=5) ImgLabel1 = Label(image=Img1) ImgLabel1.grid(row=1, column=0, padx=5, pady=5) ImgLabel2 = Label(image=Img2) ImgLabel2.grid(row=1, column=1, padx=5, pady=5) # 标签定义 myLabel = Label(root, text=" ", font=("Arial", 35)) myLabel2 = Label(root, text=" ", font=("Arial", 35)) myLabel4 = Label(root, text=" ", font=("Arial", 35)) myLabel.grid(row=2, column=0) myLabel2.grid(row=2, column=1) myLabel4.grid(row=2, column=2) # 启动手势识别子线程 threading.Thread(target=fcf, daemon=True).start() # 启动UI定时刷新 update_ui() root.mainloop()
注意事项
- 原手势识别脚本中
if __name__=='main'是错误写法,已修正为if __name__=='__main__' - 识别结果和UI动作的映射规则可以根据你的需求自行修改,需要传递完整的fingers列表直接把共享变量改成列表即可
- UI刷新间隔可以根据你的流畅度需求调整,100-300毫秒之间都可以,间隔太小会占用过多CPU资源
内容的提问来源于stack exchange,提问作者LMB
相关产品推荐
相关产品推荐

