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()
关键修改说明:
- 避免事件循环阻塞:使用
root.after(100, assistant_loop)调度语音循环,after()会在Tkinter事件循环空闲时执行语音逻辑,不会阻塞UI响应。 - UI线程安全:所有文本插入、图片显示/隐藏操作都在主线程执行,保证Tkinter的线程安全性。
- 窗口关闭处理:绑定
WM_DELETE_WINDOW事件,关闭窗口时直接终止程序,避免后台残留进程。 - 需求适配:添加了两个不同颜色的文本框分别展示用户命令和助手结果,语音识别过程中显示指定图片(需自行替换图片路径)。
内容的提问来源于stack exchange,提问作者AJITH KUMAR
相关产品推荐
相关产品推荐

