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

Python语音助手嵌入Tkinter GUI问题:窗口与语音功能不同步

解决Tkinter与语音助手同步运行的问题

你当前代码的核心问题是Tkinter的mainloop()会阻塞后续代码执行——调用winn()后,程序会卡在root.mainloop(),直到窗口关闭才会执行后面的语音助手逻辑。要让GUI和语音助手同步运行,需要将语音逻辑融入Tkinter的事件循环,同时保证UI操作的线程安全性。

下面是整合后的完整代码,实现了你所有需求:

  • 启动程序时窗口与语音助手同步运行
  • 语音识别过程中显示图片
  • 用户命令和处理结果用不同颜色文本框展示
  • 关闭窗口时程序完全终止
import tkinter as tk
from tkinter import Text, Label
import wikipedia
import speech_recognition as sr
import pyttsx3
import os
import datetime
import pyjokes
import sys

# 初始化语音引擎
engine = pyttsx3.init('sapi5')
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[1].id)

def speak(audio):
    engine.say(audio)
    engine.runAndWait()
    # 将助手的语音内容插入到结果文本框
    assistant_text.insert(tk.END, f"助手: {audio}\n")
    assistant_text.see(tk.END)

def wishMe():
    hour = int(datetime.datetime.now().hour)
    if hour >= 0 and hour < 12:
        speak("Good Morning Sir !")
    elif hour >= 12 and hour < 18:
        speak("Good Afternoon Sir !")
    else:
        speak("Good Evening Sir !")
    assname = "Voice Assisant"
    speak("I am your Assistant")
    speak(assname)

def username():
    speak("What should i call you sir")
    uname = takeCommand()
    speak("Welcome Mister")
    speak(uname)
    speak("How can i Help you, Sir")

def takeCommand():
    # 显示监听图片
    listening_label.config(image=listening_img)
    root.update_idletasks()

    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("Listening...")
        r.pause_threshold = 1
        audio = r.listen(source)
    
    try:
        print("Recognizing...")
        query = r.recognize_google(audio, language='en-in')
        print(f"User said: {query}\n")
        # 将用户命令插入到文本框
        user_text.insert(tk.END, f"你: {query}\n")
        user_text.see(tk.END)
    except Exception as e:
        print(e)
        print("Unable to Recognize your voice.")
        speak("Unable to Recognize your voice.")
        query = "None"
    finally:
        # 隐藏监听图片
        listening_label.config(image='')
        root.update_idletasks()
    return query

def assistant_loop():
    query = takeCommand().lower()
    if 'wikipedia' in query:
        speak('Searching Wikipedia...')
        query = query.replace("wikipedia", "")          
        results = wikipedia.summary(query, sentences=3)
        speak("According to Wikipedia")
        print(results)
        speak(results)
    elif 'the time' in query:
        strTime = datetime.datetime.now().strftime("%H:%M")
        speak(f"Sir, the time is {strTime}")
    elif 'how are you' in query:
        speak("I am fine, Thank you")
        speak("how are you, Sir")
    elif 'fine' in query:
        speak("It's good to know that your fine")
    elif "what's your name" in query or "What is your name" in query:
        speak("My Boss call me Mayuri")
        speak("But my friends call me Mayu")
    elif "do you have friends" in query:
        speak("Yes I have many friends")
    elif "who is your best friend" in query:
        speak("I have many friends but for me , Amenda is my best friend")
    elif 'exit' in query:
        speak("Thanks for giving me your time")
        root.destroy()
        sys.exit()
    elif "who made you" in query or "who created you" in query:
        speak("I have been created by Gokul Raj")
    elif "I love you" in query:
        speak("ooo no but I have already have a boyfriend")
    elif 'joke' in query:
        joke = pyjokes.get_joke()
        speak(joke)
    elif "will you be my girlfriend" in query:
        speak("I'm not sure about, may be you should give me some time")
    
    # 继续调度下一次语音监听
    root.after(100, assistant_loop)

def on_closing():
    root.destroy()
    sys.exit()

# 初始化GUI
root = tk.Tk()
root.title('Voice Assistant')
root.geometry('500x600')
root['background'] = 'skyblue'
root.protocol("WM_DELETE_WINDOW", on_closing)

# 加载监听图片(请替换为你的图片路径)
try:
    listening_img = tk.PhotoImage(file="listening.png")
except:
    listening_img = None
    print("未找到监听图片,跳过显示")

# 用户命令文本框(蓝色字体)
user_text = Text(root, fg="blue", wrap=tk.WORD, height=10, width=55)
user_text.pack(pady=10, padx=10)
user_text.insert(tk.END, "用户命令:\n")
user_text.config(state=tk.NORMAL)

# 助手结果文本框(绿色字体)
assistant_text = Text(root, fg="green", wrap=tk.WORD, height=10, width=55)
assistant_text.pack(pady=10, padx=10)
assistant_text.insert(tk.END, "助手回复:\n")
assistant_text.config(state=tk.NORMAL)

# 监听状态图片标签
listening_label = Label(root, bg='skyblue')
listening_label.pack(pady=10)

# 启动语音助手流程
wishMe()
username()
# 调度语音循环,避免阻塞UI
root.after(100, assistant_loop)

# 启动Tkinter事件循环
root.mainloop()

关键修改说明:

  1. 避免事件循环阻塞:使用root.after(100, assistant_loop)调度语音循环,after()会在Tkinter事件循环空闲时执行语音逻辑,不会阻塞UI响应。
  2. UI线程安全:所有文本插入、图片显示/隐藏操作都在主线程执行,保证Tkinter的线程安全性。
  3. 窗口关闭处理:绑定WM_DELETE_WINDOW事件,关闭窗口时直接终止程序,避免后台残留进程。
  4. 需求适配:添加了两个不同颜色的文本框分别展示用户命令和助手结果,语音识别过程中显示指定图片(需自行替换图片路径)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:20:34