Reputation: 365
I'm creating a text adventure in python using tkinter due to it's easy to use graphics (buttons and such)
I want to add a effect where the text looks like it's being typed out.
def displayNextPart():
for i in buttons:
i.destroy()
global curPart
for char in story[curPart]["Text"]:
slp(.05)
w.config(text=char)
sys.stdout.flush()
But the window just freezes until it's finished and all it leaves me with is the last character of the string.
Can anyone help me?
Upvotes: 3
Views: 2951
Reputation: 1192
I think this answer is the more simple and easy than any of the above answer
The Solution is:
from tkinter import *
root=Tk()
import sys
from time import sleep
words = "Typing effect in tkinter.py"
def update():
l=[]
for i in words:
l.append(i)
root.after(1000)
b="".join(l)
c=len(b)
ab.set(f"{b[0:c-1]}{i}")
a.update()
d=Button(text="click",command=update)
d.pack()
ab=StringVar()
a=Label(textvariable=ab)
a.pack()
root.mainloop()
Or just use a StringVar:
from tkinter import *
root=Tk()
words = "Typing effect in tkinter.py"
ab=StringVar()
a=Label(textvariable=ab)
a.pack()
for i in words:
a=ab.get()
ab.set(a+i)
root.after(1000)
root.update()
root.mainloop()
I have just read the letters in text, then saved that text in the StringVar, also took the previous value and added the new value to StringVar.
Upvotes: 1
Reputation: 49330
time.sleep()
does not work properly with Tkinter applications. Use the after()
method as in the following example:
import tkinter as tk
root = tk.Tk()
word = 'hello'
def go(counter=1):
l.config(text=word[:counter])
if counter < len(word):
root.after(150, lambda: go(counter+1))
b = tk.Button(root, text='go', command=go)
l = tk.Label(root)
b.pack()
l.pack()
root.mainloop()
Upvotes: 5
Reputation: 386352
You need to let the event loop update the screen. The simplest way to do that is to write a self-repeating function using tkinter's after
method.
Here's a working example. This uses a text widget, but you can just as easily update a label widget or canvas text item.
import Tkinter as tk
def typeit(widget, index, string):
if len(string) > 0:
widget.insert(index, string[0])
if len(string) > 1:
# compute index of next char
index = widget.index("%s + 1 char" % index)
# type the next character in half a second
widget.after(250, typeit, widget, index, string[1:])
root = tk.Tk()
text = tk.Text(root, width=40, height=4)
text.pack(fill="both", expand=True)
typeit(text, "1.0", "Hello, this is an \nexample of some text!")
root.mainloop()
Upvotes: 3