Is there a way to print letter by letter (redraw between frame update) in Python 3.4.1 using Tkinter?
This is doable in the normal IDLE window using this piece of code:
import time
string = "hello world"
for char in string:
print(char, end='')
time.sleep(.25)
But I can't do this in GUI Tkinter window. In my opinion, I could display a label on to the tkinter window, add a letter from a string into it, and wait for a period of time before adding another letter (about 0.25 secs), with the same idea as the code above.
Any solutions?
For example:
String To Display = 'abc'
First frame : 'a'
Second frame : 'ab'
Third Frame : 'abc'
Thanks in advance!
You didn't specify much so I just guessed you'd like something like this:
import time
import tkinter as tk
def printString(string):
for char in string:
Label.configure(text=Label.cget('text') + char)
Label.update()
time.sleep(.25)
root = tk.Tk()
text = "Hello world!"
Label = tk.Label(root)
Label.pack()
printString(text)
root.mainloop()
UPDATE:
Same principle but for a canvas:
import time
import tkinter as tk
def printString(item, string):
if item:
for char in string:
idx = c.index(item, tk.END)
c.insert(item, idx, char)
c.update()
time.sleep(.25)
root = tk.Tk()
text = "Hello world!"
c = tk.Canvas(root)
c_txt = c.create_text(50,50)
c.pack()
c.update()
printString(c_txt, text)
root.mainloop()
You can do this using after to call a method periodically to update the GUI. time.sleep is not as easy to work with as it blocks main-thread which the GUI runs on.
You could periodically replace the label's single character text with next letter in the string:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letter():
global label
label['text'] = label.string[label.current_char_index]
label.current_char_index += 1
label.current_char_index %= len(label.string)
label.after(250, update_label_letter)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root)
label.string = "Hello World!"
label.current_char_index = 0
root.after(250, update_label_letter)
label.pack()
root.mainloop()
One way would be to periodically append the letters of a single label.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global label
_no_of_space_replacements = label['text'].count('\n')
_last_char_index = len(label['text']) - _no_of_space_replacements
if _last_char_index < len(label.string):
label['text'] += label.string[_last_char_index].replace(" ", " \n")
else:
label['text'] = ""
label.after(250, update_label_letters)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root, wraplength=1)
label.string = "Hello World!"
root.after(250, update_label_letters)
label.pack()
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global label
_last_char_index = len(label['text'])
if _last_char_index < len(label.string):
label['text'] += label.string[_last_char_index]
else:
label['text'] = ""
label.after(250, update_label_letters)
if __name__ == '__main__':
root = tk.Tk()
label = tk.Label(root)
label.string = "Hello World!"
root.after(250, update_label_letters)
label.pack()
root.mainloop()
Another way would be to write the letters periodically to empty but shown letter_labels.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
_current_char = my_string[current_char_index]
letter_labels[current_char_index]['text'] = _current_char
letter_labels[current_char_index].after(250, update_label_letters)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for index, value in enumerate(my_string):
letter_labels.append(tk.Label(root))
letter_labels[index].pack()
current_char_index = 0
root.after(250, update_label_letters)
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def update_label_letters():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
_current_char = my_string[current_char_index]
letter_labels[current_char_index]['text'] = _current_char
letter_labels[current_char_index].after(250, update_label_letters)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for index, value in enumerate(my_string):
letter_labels.append(tk.Label(root))
letter_labels[index].pack(side='left')
current_char_index = 0
root.after(250, update_label_letters)
root.mainloop()
Another way would be to display the letter_labels periodically.
Vertical:
try:
import tkinter as tk
except:
import Tkinter as tk
def show_label():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
letter_labels[current_char_index].pack()
letter_labels[current_char_index].after(250, show_label)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for _char in my_string:
letter_labels.append(tk.Label(root, text=_char))
current_char_index = 0
root.after(250, show_label)
root.mainloop()
Horizontal:
try:
import tkinter as tk
except:
import Tkinter as tk
def show_label():
global current_char_index, my_string, letter_labels
if current_char_index < len(my_string):
letter_labels[current_char_index].pack(side='left')
letter_labels[current_char_index].after(250, show_label)
current_char_index += 1
if __name__ == '__main__':
root = tk.Tk()
my_string = "Hello World!"
letter_labels = list()
for _char in my_string:
letter_labels.append(tk.Label(root, text=_char))
current_char_index = 0
root.after(250, show_label)
root.mainloop()
Related
when I run this code for **Exemple ** then I click on the ttk entry and press enter it print ----> "ttk_entry"
But when I do the same thing to the customtkinter.CTkEntry it print **nothing **.
import customtkinter
from tkinter import *
def test(event):
if root.focus_get() == custom_entry:
print("custom_entry")
elif root.focus_get() == ttk_entry:
print("ttk_entry")
root = customtkinter.CTk()
custom_entry = customtkinter.CTkEntry(root) #CTkEntry
custom_entry.pack()
ttk_entry = Entry(root) #ttk_entry
ttk_entry.pack()
root.bind("<Return>", test)
root.mainloop()
I was expecting that it print "custom_entry" .
from cgitb import text
from distutils.cmd import Command
import tkinter as tk
from socket import timeout
import time
import pyfirmata
import time
from time import sleep, strftime
from tkinter import Tk, Label
from tkinter import Tk, Label
import random
import os
import tkinter.font as tkFont
ports="COM4"
board = pyfirmata.Arduino('COM4')
analog_pin0 = board.get_pin('a:1:i')
x=0
it = pyfirmata.util.Iterator(board)
it.start()
pin=4
analog_pin0.enable_reporting()
board.digital[7].write(0)
voltage0 = ""
def main():
print("this is maoin")
def on():
global voltage0
root = tk.Tk()
root.geometry("600x500")
w = tk.Label(root, text="Hello, world!")
w.pack(pady=20)
# B = tk.Button(root, text ="Hello", command = main)
# B.pack()
w.config(text=voltage0)
w['text'] = "intial voltage"
B = tk.Button(root, text ="Hello", command = main)
B.pack()
root.mainloop()
def main ():
while True:
global voltage0
reading0 = analog_pin0.read()
if reading0 != None:
voltage0 = reading0 * 22.3
voltage0 = round(voltage0,2)
time.sleep(0.1)
print(voltage0)
w.config(text=voltage0)
w['text'] = voltage0
else:
voltage0 = float('nan')
string = strftime('%H:%M:%S %p')
if (voltage0>7.3):
time.sleep(0.1)
board.digital[pin].write(1)
board.digital[6].write(0)
if(voltage0<6.5):
time.sleep(0.1)
board.digital[pin].write(0)
board.digital[6].write(1)
if (voltage0==7.3):
print()
print(voltage0)
print(string)
w.config(text=voltage0)
w['text'] = voltage0
if (voltage0==6.5):
print()
print(voltage0)
print(string)
w.config(text=voltage0)
w['text'] = voltage0
main()
on()
As per object, the progress bar is displayed only at the end of the completion of the for loop. Instead I would like it to show the progress of the cycle step by step.
from tkinter import ttk
from tkinter import *
import time
def inner_loop_func():
k = 0
for i in range(10**5):
k=k+1
print("k: ",k)
def loop_fun():
p = ttk.Progressbar(root, orient="horizontal", length=300, mode="determinate", takefocus=True, maximum=100)
p['value'] = 0
p.pack()
end = 100
for i in range(end):
start(end,p)
inner_loop_func()
print(i," of ", end)
def start(end,p):
if p['value'] < 300:
p['value'] += (300/end)
else:
print("finish")
if __name__ == "__main__":
root = Tk()
loop_fun()
root.mainloop()
Use p.update() inside the loop_fun function for loop:
for i in range(end):
start(end, p)
inner_loop_func()
print(i, " of ", end)
p.update()
Can anyone tell me how to make if statement if the text of button is equal example like this code
from tkinter import *
app = Tk()
def k():
#i know this is wrong so plss correct me
if button1.text == "1":
l = Label(app,text="wow")
l.pack
button1 = Button(app,text="1",command=k).pack()
app.mainloop()
Plss tell me thank you
Since the object of tkinter consists of a dictionary, you can get a value by accessing the key value 'text'.
from tkinter import *
app = Tk()
def k():
if button1["text"] == "1":
l = Label(app,text="wow")
l.pack()
button1 = Button(app,text="1",command=k)
button1.pack()
app.mainloop()
I am trying to write code that will return either head or tails and show it in a separate window (message box). How can I show the result of my function in a separate window (message box)?
import tkinter
import numpy as np
from tkinter import messagebox
result = []
def hola():
coin = np.random.randint(0,2)
if coin == 0:
result.append("heads")
else:
result.append("tails")
messagebox.showinfo( "Lucky you !", result )
top = tkinter.Tk()
B = tkinter.Button(top, text ="flip da coin", command = hola)
B.pack()
top.mainloop()
I think you want to do something like this;
import tkinter
import numpy as np
from tkinter import messagebox
def hola():
coin = np.random.randint(0,2)
if coin == 0:
result = "heads"
else:
result = "tails"
messagebox.showinfo( "Lucky you !", result )
top = tkinter.Tk()
B = tkinter.Button(top, text ="flip da coin", command = hola)
B.pack()
top.mainloop()