I've been googling for almost a week now and I know there are similar questions, but none of them have an answer. So here is one more, which hopefully will lead to an answer. I wrote a small program for my kid where a word shows up, is pronounced and after clearing the word she needs to reproduce it. I used pyttsx3 as a speech module because it's available offline. Program works fine, but just to make it more attractive for her, I decided to build a GUI with tkinter. What happens now is that the window is built, the word shows up is pronounced, but after that the program shuts down without any errors. To check how far the program is executed, I used a print command after every line. The print commands are executed, and are visible in the terminal. Every other line in between, related to tkinter is not executed. I tried to create a different function for the speak engine, same thing happens.
So again: pyttsx3 works fine, so does tkinter, but together in one program does not. if you remove the line engine.runAndWait() the program executes fine, just without speech.
Why is this happening and how can I solve it? I am very sorry, please explain it to me like I'm a 40 year old housefather who is trying to learn a new skill without any background in programming or CS, thanks.
Here is my code, sorry if it's a bit messy, just started a few weeks ago :-)
import tkinter as tk
import sys, json, random, pyttsx3
#setup window
window = tk.Tk()
window.geometry("500x500")
window.title("Aliyah's dictee spel")
window.configure(background = "black")
#my photo
photo1 = tk.PhotoImage(file="dictee.gif")
tk.Label (window, image=photo1, bg="black") .grid(row=0, column=0)
def main():
"""Setting up the game"""
global WORDS_CORRECT, WORDS_WRONG, WORDS
WORDS_CORRECT = 0
WORDS_WRONG = 0
with open('vocabulary.json') as json_file:
data = json.load(json_file)
WORDS = data["words"]
for widget in window.winfo_children():
widget.destroy()
tk.Label (window, image=photo1, bg="black") .grid(row=0, column=0)
tk.Label (window, text = "Dit is het dictee spel voor Aliyah. Wil je beginnen?", bg="black", fg="white", font="none 12 bold") .grid(row=1)
tk.Button(window, text="Ja", width=6, command=lambda: dictee(WORDS)) .grid(row=2, column=0)
tk.Button(window, text="Nee", width=6, command=sys.exit) .grid(row=2, column=1)
tk.Button(window, text="Bewerk lijst", width=10, command=manage_list) .grid(row=3, column=1)
#def speak(WORD): this did not work, even the last print command in dictee() is executed in terminal
#engine = pyttsx3.init()
#nl_voice_id = "com.apple.speech.synthesis.voice.ellen"
#engine.setProperty('rate', 100)
#engine.setProperty('voice', nl_voice_id)
#engine.say(WORD)
#engine.runAndWait()
def dictee(WORDS):
"""Show random words and ask for input."""
if WORDS == []:
for widget in window.winfo_children():
widget.destroy()
tk.Label (window, image=photo1, bg="black") .grid(row=0, column=0)
tk.Label (window, text = "Dat waren alle woordjes.", bg="black", fg="white", font="none 12 bold") .grid(row=1, column=0)
tk.Label (window, text = "Woordjes goed: %d" % WORDS_CORRECT, bg="black", fg="white", font="none 12 bold") .grid(row=2, column=0)
tk.Label (window, text = "Woordjes fout: %d" % WORDS_WRONG, bg="black", fg="white", font="none 12 bold") .grid(row=3, column=0)
tk.Label (window, text = "Wil je het nog een keer proberen?", bg="black", fg="white", font="none 12 bold") .grid(row=4, column=0)
tk.Button(window, text="Ja", width=6, command=main) .grid(row=5, column=0)
tk.Button(window, text="Nee", width=6, command=exit_game) .grid(row=5, column=1)
window.update()
else:
random.shuffle(WORDS)
for widget in window.winfo_children():
widget.destroy()
WORD = WORDS[0]
tk.Label (window, image=photo1, bg="black") .grid(row=0, column=0)
word = tk.Label (window, text = WORD, bg="black", fg="white", font="none 20 bold")
word.grid(row=1, column=0)
window.update()
#speak(WORD)this is related to speak()
engine = pyttsx3.init()
nl_voice_id = "com.apple.speech.synthesis.voice.ellen"
engine.setProperty('rate', 100)
engine.setProperty('voice', nl_voice_id)
engine.say(WORD) #WORD is being said!
engine.runAndWait()#<< if you remove this line, the program is executed fine, but without speech
#engine.stop() this did not work
window.after(3000)
print('after after')#all print commands after this are executed in terminal, all other lines are not executed
word['text'] = ''
print('after clear text')
window.update()
print('after update')
ANSWER = tk.Entry(window, width=20, bg="white")
print('after creating entry box')
ANSWER.grid(row=2, column=0)
print('after positioning entry window')
tk.Button(window, text="Check", width=6, command=lambda: check(ANSWER,WORD)) .grid(row=3, column=0)
print('after creating button')
WORDS.remove(WORD)
print('after words.remove')
def check(ANSWER, WORD):
'''Cross check word shown with answer given'''
global WORDS_CORRECT, WORDS_WRONG
if ANSWER.get() == WORD:
tk.Label (window, text = "Wat goed!", bg="black", fg="white", font="none 12 bold") .grid(row=4, column=0)
WORDS_CORRECT += 1
else:
tk.Label (window, text = "Jammer!", bg="black", fg="white", font="none 12 bold") .grid(row=4, column=0)
WORDS_WRONG += 1
tk.Label (window, text = "Wil je het nog een keer proberen?", bg="black", fg="white", font="none 12 bold") .grid(row=5, column=0)
tk.Button(window, text="Ja", width=6, command=lambda: dictee(WORDS)) .grid(row=6, column=0)
tk.Button(window, text="Nee", width=6, command=exit_game) .grid(row=6, column=1)
def manage_list():
'''manage the list of words by user'''
with open('vocabulary.json', "r") as f:
data = json.load(f)
WORDS = data["words"]
for widget in window.winfo_children():
widget.destroy()
window.update()
tk.Label (window, text = "Dit zijn alle woorden in de vocabulaire", bg="black", fg="white", font="none 12 bold") .grid(row=0, column=0)
tk.Label (window, text = WORDS, bg="black", fg="white", font="none 12 bold") .grid(row=1, column=0)
tk.Label (window, text = "Wil je woorden toevoegen of verwijderen?", bg="black", fg="white", font="none 12 bold") .grid(row=2, column=0)
tk.Button(window, text="alles verwijderen", command=lambda: clear_words('vocabulary.json')) .grid(row=5, column=0)
words_to_add = tk.Entry(window, width=40, bg="white")
words_to_add.grid(row=3, column=0)
tk.Button(window, text="toevoegen", width=6, command=lambda: add_words('vocabulary.json', words_to_add.get())) .grid(row=8, column=2)
tk.Button(window, text="hoofdmenu", width=6, command=main) .grid(row=10, column=0)
def add_words(filename, wordt_text):
with open(filename, "r+") as f:
data = json.load(f)
data["words"].extend(wordt_text.split())
f.seek(0)
json.dump(data, f, indent=4)
manage_list()
def clear_words(filename):
with open('vocabulary.json', "w+") as f:
data = {"words":[]}
json.dump(data, f, indent=4)
manage_list()
def exit_game():
'''summarize results and exit after pushing enter'''
for widget in window.winfo_children():
widget.destroy()
tk.Label (window, image=photo1, bg="black") .grid(row=0, column=0)
tk.Label (window, text = "Tot de volgende keer.", bg="black", fg="white", font="none 12 bold") .grid(row=1, column=0)
tk.Label (window, text = "Woordjes goed: %d" % WORDS_CORRECT, bg="black", fg="white", font="none 12 bold") .grid(row=2, column=0)
tk.Label (window, text = "Woordjes fout: %d" % WORDS_WRONG, bg="black", fg="white", font="none 12 bold") .grid(row=3, column=0)
tk.Label (window, text = "Klik op OK om af te sluiten", bg="black", fg="white", font="none 12 bold") .grid(row=4, column=0)
tk.Button(window, text="OK", width=6, command=sys.exit) .grid(row=5, column=0)
if __name__ == "__main__":
main()
window.mainloop()
Here is the vocabulary.json file:
{
"words": [
"huis",
"muis",
"bal",
"vuur",
"muur",
"ik",
"zon",
"hok",
"poep",
"aap",
"noot",
"hij",
"zij",
"test",
"woord"
]
}
here is a link to the image I used: https://www.obsbeekbergen.nl/wp-content/uploads/sites/34/2016/04/dictee.gif
The output in the terminal when the program is shut down (again, no errors):
after clear text
after update
after creating entry box
after positioning entry window
after creating button
after words.remove
I'm using python 3.8.5 with MacOs Mojave 10.14.6.