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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:54:02