在Tkinter中运行无限循环时如何使用关闭(X)或任何其他按钮

问题描述 投票:0回答:1

我正在编写用于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()
python windows user-interface tkinter python-multithreading
1个回答
0
投票

您在这里考虑穿线是正确的。

标准线程库就足够了。您将要创建两个类,一个用于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()

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.