我正在编写用于GUI的程序,以使用tkinter支持我的Voice Assistant Python脚本。但是问题在于,一旦激活了语音助手程序,即会不断执行用户所说内容的功能的无限循环,整个窗口冻结,我无法单击任何其他按钮,而且我无法也访问关闭(X)按钮。我知道在这种情况下我需要使用线程,但是我并不清楚要在哪里使用它来实现我的期望。如果有人可以帮助我,我将非常有义务。我将提供为帮助您解决问题而编写的全部代码。程序中的无限运行功能为Geega()
from tkinter import *
import tkinter.font as font
import tkinter.messagebox as tmsg
import pyttsx3
import speech_recognition as sr
import datetime
import wikipedia
import webbrowser
import os
import time
import smtplib
import random
import wolframalpha
import apiai
import json
import _thread
#API configuration
engine = pyttsx3.init('sapi5')
client = wolframalpha.Client('AQKXVX-UVQ8TUWUVU')
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[1].id)
#Conversation mode
def convo_mode():
Text_frame1['text'] = "Geega has entered conversation mode..."
Button_frame1 = Button(Frame1, image=Button_image, bg='#444444', borderwidth=0, height=200, width=200, state=DISABLED, activebackground='#444444').place(x=5,y=15)
# Button_frame3 = Button(Frame3, text='Button', bg='white', borderwidth=0, cursor='hand2', state=DISABLED, activebackground='#444444').place(x=5,y=15)
Button_frame3 = Button(Frame3, image=Button_image2, bg='#333333', borderwidth=0, height=80, width=250, cursor='hand2', command=convo_mode, state=DISABLED, activebackground='#333333').place(x=320,y=360)
main_window.update()
speak("Geega has entered Conversation mode...")
query = takeCommand().lower()
while "back" not in query:
response = apiai_connc(query)
speak(response)
query = pause().lower()
else:
speak("Re-entering Normal Mode...")
Button_frame1 = Button(Frame1, image=Button_image, bg='#444444', borderwidth=0, height=200, width=200, state=NORMAL, cursor= 'hand2', activebackground='#444444', command=Geega).place(x=5,y=15)
# Button_frame3 = Button(Frame3, text="Button", bg='white', borderwidth=0, cursor='hand2', state=NORMAL, activebackground='#444444', command = convo_mode).place(x=5,y=15)
Button_frame3 = Button(Frame3, image=Button_image2, bg='#333333', borderwidth=0, height=80, width=250, cursor='hand2', command=convo_mode, state=NORMAL, activebackground='#333333').place(x=320,y=360)
Text_frame1['text'] = "Geega has entered Normal mode..."
main_window.update()
#Function for instructions
def Instructions():
Instruction = tmsg.showinfo("Instructions", "- Click the mic to activate Geega\n\n- Say \'Hello Geega\' before each command to make Geega do it\n\n- Click on \'Turn on Conversation Mode\' to enter Conversation Mode to make Geega answer your questions!\n\nNote: Geega would not execute command when running in Conversation mode. To bring back Geega to normal mode, just speak \'Back\'.")
#Function for About Geega
def About_Geega():
copyright_symbol = u"\u00A9"
About_Geega = tmsg.showinfo("About Geega", u"Geega v1.0.0\n\nReleased on May 16, 2020\n\n%s All rights reserved" % (copyright_symbol))
#Function for authors
def Authors():
Author = tmsg.showinfo("Authors","Designed by Soham Chatterjee")
#Function to make Geega speak
def speak(audio):
engine.say(audio)
engine.runAndWait()
#Function to make Geega wish the user
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!")
speak("I am Geega - the personal Voice Assistant. Just speak \"Hello Geega\" to activate me. I am always there for your service!")
#Function to take command from user
def takeCommand():
r = sr.Recognizer()
with sr.Microphone(device_index=1) as source:
r.pause_threshold = 1
audio = r.listen(source)
query = ''
try:
query = r.recognize_google(audio, language='en-in')
except sr.UnknownValueError:
speak("Sorry! Couldn\'t get you!! Please say again")
return takeCommand().lower()
except sr.RequestError:
print("Aw, Snap! Geega is down!! Please restart the program!")
return takeCommand().lower()
return query.lower()
#Function to pause when user is doing any work
def pause():
r = sr.Recognizer()
with sr.Microphone() as source:
r.pause_threshold = 1
audio = r.listen(source)
query = ''
try:
query = r.recognize_google(audio, language='en-in')
except sr.UnknownValueError:
return pause().lower()
except sr.RequestError:
return pause().lower()
return query
#Function for API connection
def apiai_connc(voice_data):
CLIENT_ACCESS_TOKEN = "6b496c3a7afe409da201e7e82b3b5215"
ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
request = ai.text_request()
request.lang = "de"
request.session_id = "<SESSION ID, UNIQUE FOR EACH USER>"
request.query = voice_data
source = request.getresponse()
source_data = source.read()
obj = json.loads(source_data)
return obj["result"]["fulfillment"]["speech"]
#Main Geega function
def Geega():
Button_frame3 = Button(Frame3, image=Button_image2, bg='#333333', borderwidth=0, height=80, width=250, cursor='hand2', command=convo_mode, state=DISABLED, activebackground='#333333').place(x=320,y=360)
Text_frame1['text'] = "Geega is running..."
main_window.update()
wishMe()
while True:
query = pause().lower()
if query.count("hello")>0:
speak("Hello sir! Geega is ready to be instructed...")
query = takeCommand().lower()
if query == '':
speak("Sorry! I couldn't hear you! Can you please say that again?")
elif 'youtube' in query:
speak("Opening YouTube...")
webbrowser.open("www.youtube.com")
elif 'google' in query:
speak("Opening Google...")
webbrowser.open("www.google.com")
elif 'meet' in query:
speak("Opening Google Meet...")
webbrowser.open("https://meet.google.com")
elif 'physics class' in query:
speak("Opening your Physics class on Google Meet...")
webbrowser.open("https://meet.google.com/inw-ncmr-emq")
elif 'mathematics' in query:
speak("Opening your Mathematics class on Google Meet...")
webbrowser.open("https://meet.google.com/inw-ncmr-emq")
elif 'chemistry class' in query:
speak("Opening your Chemistry class on Google Meet...")
webbrowser.open("https://meet.google.com/inw-ncmr-emq")
elif 'english class' in query:
speak("Opening your English class on Google Meet...")
webbrowser.open("https://meet.google.com/eym-ypwa-kkx")
elif 'play music' in query:
music_dir = 'E:\\Bony Laptop\\Music'
songs = os.listdir(music_dir)
speak("Playing music...")
os.startfile(os.path.join(music_dir,songs[0]))
elif 'day' in query:
now = datetime.datetime.now()
day = now.strftime("%A")
speak(f"Today is {day}")
elif 'date' in query:
date = datetime.datetime.now().strftime("%B")
speak(f"Today's date is {date}")
elif 'time' in query:
strTime = datetime.datetime.now().strftime("%I:%M:%S")
speak(f"The time is {strTime}")
elif 'browser' in query:
speak('Sure! Opening Internet Explorer...')
browser_path = webbrowser.open(url="google.com")
elif 'open python' in query:
python_path = "C:\\Users\\admin\\AppData\\Local\\Programs\\Python\\Python38-32\\Lib\\idlelib\\idle.pyw"
speak("Opening Python...")
os.startfile(python_path)
elif 'calculate' in query:
query = query
speak("Calculating...")
try:
res = client.query(query)
results = next(res.results).text
speak(f"The results are {results}")
except:
speak("Oops! Something went wrong. I couldn't calculate the problem.")
elif 'exit' in query or "quit" in query:
speak("Good Bye Sir! Have a nice day!")
quit()
elif 'search' in query:
speak("Searching on the Web...")
url = 'https://www.google.co.in/search?q='+query
webbrowser.get().open(url)
elif 'weather' in query:
speak("Getting weather forecast results for your location on Google...")
url = 'https://www.google.co.in/search?q=weather'
webbrowser.get().open(url)
elif 'i want to talk to you' in query:
convo_mode()
else:
speak("Could not get you!")
main_window = Tk()
def close(event):
global main_window
key = event.char
if key == "<ESCAPE>":
main_window.destroy()
_thread.start_new_thread(main_window.bind("<Key>", lambda a: close(a)))
#Window configuration
windowWidth = 500
windowHeight = 300
screen_width = main_window.winfo_screenwidth()
screen_height = main_window.winfo_screenheight()
x_coordinate = (screen_width/2)-(windowWidth/2)
y_coordinate = (screen_height/2)-(windowHeight/2)
#Main Window Configuration
main_window.configure(bg='white')
main_window.iconbitmap('Geega_logo.ico')
main_window.title("Geega")
main_window.geometry('%dx%d+%d+%d' % (windowWidth, windowHeight, x_coordinate, y_coordinate))
main_window.minsize(500,300)
main_window.update()
#Frame 1 for Speak button
Frame1 = Frame(main_window, bg='#444444', borderwidth=5)
Frame1.place(x=0, y=0, width=500, height=300)
#Frame 2 for features
Frame2 = Frame(main_window, bg='#555555', borderwidth=5)
Frame2.place(x=0,y=300, width=500, height=440)
#Frame 3 for conversation mode
Frame3 = Frame(main_window, bg='#333333', borderwidth=5)
Frame3.place(x=500,y=0, width=865, height=740)
#Defining the font
Font = font.Font(family='Segoe UI', size=15, weight='bold')
Font2 = font.Font(family='Segoe UI', size=15)
Font3 = font.Font(family='Segoe UI', size=30)
#Defining the menu bar
MenuBar= Menu(main_window)
Drop_down1 = Menu(MenuBar, tearoff=0)
Drop_down1.add_command(label="Instructions", command=Instructions)
Drop_down1.add_separator()
Drop_down1.add_command(label='About Geega', command=About_Geega)
Drop_down1.add_command(label='Authors', command=Authors)
#Adding the menu bar
main_window.config(menu=MenuBar)
MenuBar.add_cascade(label="Help", menu=Drop_down1)
#Frame 1 button configuration
Button_image = PhotoImage(file="rsz_1speak_button_png.png")
Button_frame1 = Button(Frame1, image=Button_image, bg='#444444', borderwidth=0, height=200, width=200, cursor='hand2', command=Geega, activebackground='#444444').place(x=5,y=15)
#Frame 1 text configuration:
Text_frame1 = Label(Frame1, text="Click the mic to activate Geega...", bg='#444444', fg='white')
Text_frame1.place(x=43,y=225)
Text_frame1['font'] = Font
#Frame 2 text configuration
Text1_frame2 = Label(Frame2, text='Exciting things to do with Geega!', bg='#555555',fg='white')
Text1_frame2.place(x=43, y=15)
Text1_frame2['font'] = Font2
Text2_frame2 = Label(Frame2, text='- Tell her to open Google for you', bg='#555555',fg='white')
Text2_frame2.place(x=50, y=50)
Text2_frame2['font'] = Font2
Text3_frame2 = Label(Frame2, text='- Tell her to open Chrome for you', bg='#555555',fg='white')
Text3_frame2.place(x=50, y=85)
Text3_frame2['font'] = Font2
Text4_frame2 = Label(Frame2, text='- Bored? Ask Geega to play some music', bg='#555555',fg='white')
Text4_frame2.place(x=50, y=120)
Text4_frame2['font'] = Font2
Text5_frame2 = Label(Frame2, text='for you', bg='#555555',fg='white')
Text5_frame2.place(x=63, y=155)
Text5_frame2['font'] = Font2
Text4_frame2 = Label(Frame2, text='- Try out conversing with Geega in the', bg='#555555',fg='white')
Text4_frame2.place(x=50, y=185)
Text4_frame2['font'] = Font2
Text5_frame2 = Label(Frame2, text='Conversation mode', bg='#555555',fg='white')
Text5_frame2.place(x=63, y=220)
Text5_frame2['font'] = Font2
Text6_frame2 = Label(Frame2, text='Check out the other features too. Interact', bg='#555555',fg='white')
Text6_frame2.place(x=43, y=255)
Text6_frame2['font'] = Font2
Text6_frame2 = Label(Frame2, text='with Geega to find more...', bg='#555555',fg='white')
Text6_frame2.place(x=43, y=290)
Text6_frame2['font'] = Font2
Text7_frame2 = Label(Frame2, text='More new features coming soon...', bg='#555555',fg='white')
Text7_frame2.place(x=43, y=325)
Text7_frame2['font'] = Font
#Frame 3 button configuration
Button_image2 = PhotoImage(file="Convo button.png")
Button_frame3 = Button(Frame3, image=Button_image2, bg='#333333', borderwidth=0, height=80, width=250, cursor='hand2', command=convo_mode, state=NORMAL, activebackground='#333333').place(x=320,y=360)
#Frame 3 text configuration
Text_frame3 = Label(Frame3, text="Check out the all new conversation mode!", bg='#333333', fg='white')
Text_frame3.place(x=255,y=300)
Text_frame3['font'] = Font2
main_window.mainloop()
您在这里考虑穿线是正确的。
标准线程库就足够了。您将要创建两个类,一个用于GUI,另一个用于其他进程。您可以对函数执行以下操作:
import threading
...
class BackgroundProcess(threading.Thread):
def __init__(self, parent=None):
super().__init__()
self.parent = parent
def run(self):
Geega()
并且不只是从您的UI调用Geega(),而是创建一个新的BackgroundProcess对象并按如下所示调用其start()函数:
process = BackgroundProcess()
process.start()
希望这会有所帮助!