How to make tts (pyttsx3) speak something after loading the Tkinter window - python-3.x

So I am making a project which has numerous buttons and windows using Tkinter and I implemented tts using pyttsx3 module. Consider the following example:
import pyttsx3
from Tkinter import *
#configure text-to-speech
engine = pyttsx3.init()
def speak(text):
engine.setProperty("rate", 150)
engine.say(text)
engine.runAndWait()
root = Tk()
def submit():
top = Toplevel(root)
hello_world = Label(top, text = "Hello World")
hello_world.pack()
speak("Hello World")
click_me = Button(root, text = "Click Me", command = submit)
click_me.pack()
root.mainloop()
When the button is clicked the tts command will run first and the window will freeze until pyttsx3 finishes speaking and then only the window will load. And when there is a lot of text to speak this problem worsens.
What I want is that the tts command should execute after the window is loaded. How should I do this?

I had the exact same problem, I tried everything including threading
But the method
Root.after(2000, speak)
Will definitely work.
The number is in milliseconds.

Related

Webcam, Tkinter, optionmenu, thread

The following script is an attempt to choose webcam from OptionMenu in tkinter and open using thread:
class wcbm():
def __init__(self, nCam):
# a lot of code
from tkinter import *
import threading
def main():
main_window = Tk()
# Webcam list
options = [0,1,2,3,4,5,6,7,8,9]
clicked = StringVar()
clicked.set("Choose a webcam")
drop = OptionMenu(main_window, clicked, *options).pack()
btn = Button(main_window, text="Botão", command=lambda:threading.Thread(target=wbcm(clicked.get())).start()).pack()
main_window.mainloop()
if __name__ == "__main__":
main()
wbcm is a class to open webcam (opencv, dlib, ...). The only one required variable for this class is nCam.
The above script gives an error:
TypeError: 'wbcm' object is not callable
What's going on, please?
I expect with my script I may choose and show (thread) webcam from OptionMenu list options.

Changing order of execution in python

I have recently started programming and written a fairly simple program. But stuck at a point. My program does a very simple thing that when you click a button it will say a line and shows that text on the screen. But it is speaking the text first and then displays it on the screen but I want its reverse, i.e it should first display it on the screen and then speak the text.
from tkinter import *
import pyttsx3
root = Tk()
def speak():
engine = pyttsx3.init()
say = "I am speaking."
text.insert("0.0", say)
engine.say(say)
engine.runAndWait()
text = Text(root)
text.pack()
btn = Button(root, text="speak", command=speak)
btn.pack()
root.mainloop()
Thanks in advance.
It is because engine.runAndWait() blocks the application, and so text box cannot be updated by tkinter mainloop until the speaking completed.
You can call text.update_idletasks() to force tkinter to update the text box before the speaking:
engine = pyttsx3.init() # initialize only once
def speak():
say = "I am speaking."
text.insert("0.0", say)
text.update_idletasks() # force tkinter update
engine.say(say)
engine.runAndWait()
You could delay the call to engine.say
from tkinter import *
import pyttsx3
def speak(sentence):
engine.say(sentence)
engine.runAndWait()
def display_and_speak():
sentence = "I am speaking."
text.insert("1.0", sentence)
root.after(1000, speak, sentence) # call to speak delayed 1 second
engine = pyttsx3.init()
root = Tk()
text = Text(root)
text.pack()
btn = Button(root, text="speak", command=display_and_speak)
btn.pack()
root.mainloop()

Keyboard event inside a class not working in tkinter

I am trying to capture a keypress after a canvas object is displayed in order to delete the latter, and it's not working. The canvas is displayed properly, but the keypress event is not getting captured. I am a total newbie at Python and this is just a test-code to check my understanding of Tkinter so far. I'm sure it's something fairly basic that I'm missing, so thank you for your patience.
from tkinter import *
class Main:
def __init__(self,master):
# create splash screen
splash = Canvas(master, bg='white')
splash.bind("<Key>",self.splash_key)
splash.pack(fill="both", expand=True)
def splash_key(event):
print('key captured!')
splash.delete("all")
root = Tk()
root.wm_title('Test')
root.attributes('-zoomed',True)
app = Main(root)
root.mainloop()

Why is tkinter not working in visual studio?

I'm working on a new project in visual studio as shown in the code below, and the GUI using Tkinter is not working in visual studio. This is my first time using visual studio and I can't seem to find why it won't work.
from tkinter import *
import tkinter as ttk
#import os #not needed
root = Tk()
#Setting up the window
root.geometry("250x100")
root.resizable(width=False, height=False)#Disables user to resize window
root.title("Login")
#Temp "DataBase"
users=[("josh","python")] #<<<here ''josh'' is user and ''python'' i5s password
admins=[("josh1","python1")]
# Login and signup function
def login(): #login function
if (t1.get(),t2.get())in users: #Temp for testing
root.destroy()
import MainWindow
# os.system("MainWindow") #does not work
print("welcome")
elif (t1.get(),t2.get())in admins: #Temp for testing
root.destroy()
import AdminMainWindow
# os.system("AdminMainWindow") #does not work
print("welcome Admin")
else:
error.config(text="Invalid username or password")
def signup(): #signup function
root.destroy
import SignupWindow
# os.system("SignupWindow") #does not work
#arranging display varables
top = Frame(root)
bottom = Frame(root)
top.pack(side=TOP, fill=BOTH, expand=True)
bottom.pack(side=BOTTOM, fill=BOTH, expand=True)
#error placement and font
error = Label(root, font=("blod",10))
error.place(x=40,y=55)
#input display setup
l1 = Label(root,text="Username:")
l2 = Label(root,text="Password:")
t1 = Entry(root, textvariable=StringVar())
t2 = Entry(root, show="*", textvariable=StringVar())
b1 = Button(root,text="Login", command=login)
b2 = Button(root,text="Signup", command=signup)
#organising
l1.pack(in_=top, side=LEFT)
t1.pack(in_=top, side=LEFT)
l2.pack(side=LEFT,)
t2.pack(side=LEFT,)
b1.pack(in_=top, side=BOTTOM)
b2.pack(in_=bottom, side=BOTTOM)
#end of Tk loop
root.mainloop()
It comes up with the python command line and says press any key to continue.
I also looked online and they all say it because people don't end the Tk loop, but I have.
before you make a new project I created a new file and places all the code in there. then add one code to VS at a time then it works but not when you do it all together.
On ms-windows, python programs using tkinter should have the extension .pyw. And this extension should be associated with pythonw.exe rather than python.exe.
Using pythonw.exe will prevent the cmd.exe window from appearing when your python script has a GUI.

How to detect key-press combinations in background on linux & windows with python?

how can I detect key-press combinations in background using python for linux and windows ?
for example,
when Ctrl+v is detected execute doThis() in background
when Tab is detected execute doThat() in background
If you are using python tkinter, having filemenu. then below code might help you.
from Tkinter import *
import sys
import Tkinter
class App(Tkinter.Tk):
def __init__(self):
Tkinter.Tk.__init__(self)
menubar = Tkinter.Menu(self)
fileMenu = Tkinter.Menu(menubar, tearoff=False)
menubar.add_cascade(label="File", underline=0, menu=fileMenu)
fileMenu.add_command(label="doThat", underline=1,
command=quit, accelerator="Ctrl+v")
fileMenu.add_command(label="doThis", underline=1,
command=quit, accelerator="Tab")
self.config(menu=menubar)
self.bind_all("<Control-v>", self.doThat)
self.bind_all("<Tab>", self.doThis)
def doThat(self, event):
print("Control v is pressed ...")
def doThis(self, event):
print("Tab is pressed...")
if __name__ == "__main__":
app = App()
app.mainloop()
on windows this can be done using
pyhook
on ubuntu I did it with help of this
pyxhook
Edit: another awesome library for Windows & Linux - keyboard
pynput worked the best for me.

Resources