0

With the Help of Tkinter, I am trying to print a single word at a time(with an interval of 2-sec sleep) I tried the following code, It doesn't work as I want it to do. My code is printing the whole string stacked upon one another.

After n*len(words) sleep seconds are passed.

I am trying to print ONLY one word at a time(with an interval of 2-sec)

from tkinter import *
from time import sleep
root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root, text='')

for w in range(len(words)):
    sleep(2)
    l = Label(root,text = words[w])
    #l['text'] = words[w] # this is what I tried
    l.pack()
    root.mainloop()

I tried above-commented statement, thought this might update but didn't work at all as I expected.

3 Answers3

3

Take a look at this example:

from tkinter import *

root = Tk()

words = 'Hey there, This is python3'.split()
l = Label(root) #creating empty label without text
l.pack()

w = 0 #index number
def call():
    global w
    if w <= len(words)-1: #if it is in the range of the list
        l.config(text=words[w]) #change the text to the corresponding index element
        w += 1 #increase index number
        root.after(2000,call) #repeat the function after 2 seconds
    else:
        print('Done') # if out of index range, then dont repeat
call() #call the function initially

root.mainloop() 

I've commented the code to understand better.

The method using after() calls the function repeatedly, which may decrease its efficiency. So alternatively you can also use, threading to start a new thread that will not make the GUI freeze while sleep():

from tkinter import *
from time import sleep
import threading #import the library

root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root) #empty label
l.pack() #pack()

def call():
    for w in words: #loop through the list
        l.config(text=w) #update label with each word over each iteration
        sleep(2) #sleep for 2 seconds

threading.Thread(target=call).start() #create a separate thread to not freeze the GUI

root.mainloop()
halfer
  • 19,824
  • 17
  • 99
  • 186
Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
  • Hi Cool Cloud. I wonder if you're not aware that Stack Overflow aims towards a technical, succinct style of writing. With that in mind, could you try to refrain from adding thanks, and hopes that you answer helps? These will generally be excised by volunteer editors, and it would save us a bit of work if they are not added. – halfer Sep 30 '20 at 19:17
1

Simple answer that uses threading, since time.sleep(2) will make the whole tkinter wait some seconds before actually showing the window.

from tkinter import *
import time
from threading import Thread
root = Tk()

words = 'Hey there, This is python3'.split()
l = Label(root, text='')
l.pack()

def show_words():
    for word in words:
        time.sleep(2)
        l.configure(text=word)

thread = Thread(target = show_words)
thread.start()

root.mainloop()
coderoftheday
  • 1,987
  • 4
  • 7
  • 21
  • threading adds overhead, and is dangerous because tkinter isn't thread safe. – Bryan Oakley Sep 30 '20 at 16:30
  • could you elaborate further please?, I know tkinter is single threaded, but I would think making another thread would be alright? – coderoftheday Oct 01 '20 at 11:44
  • tkinter has the ability to schedule functions in the future. Updating a label every coupel of seconds is trivial, without bringing in the complexity of threading. – Bryan Oakley Oct 01 '20 at 13:51
  • if tkinter schedules a function in the future how would it effect the label?, and if the function is something to do with the label, would it matter since by then the thread be dead? – coderoftheday Oct 02 '20 at 17:35
  • The function that is scheduled in the future can do anything it wants, including updating a label. – Bryan Oakley Oct 02 '20 at 17:37
  • Configuring a label from another thread is what is unsafe. For more information about why tkinter is not thread safe see this, which was written by one of the tcl/tk developers: https://stackoverflow.com/questions/38767355/callback-to-python-function-from-tkinter-tcl-crashes-in-windows/38767665#38767665 – Bryan Oakley Oct 02 '20 at 18:54
1

well you first need to take the mainloop() out of the for loof since it just send the command to run the root again hence only first word is printed . I used a timer and a new screen as well (Note:you can do the same stuff on root as well ) ,I started the timer and and send a command to run the def after a perticular time from the current time.I hope that helped you.

from tkinter import *
import threading
from time import sleep
root = Tk()
words = 'Hey there, This is python3'.split()
l = Label(root, text='')
print(words);
def newWindow():
         global newScreen
         newScreen=Toplevel()
         newScreen.title("Rahul Screen")
         newScreen.geometry("300x300+15+15")
         newScreen.resizable(0,0)
         l=Label(newScreen,text='')
         for w in range(len(words)):
             print(w);
             sleep(2)
             l = Label(newScreen,text = words[w])
             l.pack()
start_time = threading.Timer(2,newWindow)
start_time.start()
root.mainloop()
Rahul Kumar Jha
  • 289
  • 1
  • 8