I'm a beginner in python Tkinter and I'm trying to print the characters from different lists upon clicking respective buttons. Once the button is clicked, the items from the list will keep on displaying whenever user presses any key from the keyboard. Upon pressing Enter key it should stop displaying from the current list. 1. The canvas is not cleaned up on the next iteration. The new label is created and placed at the top of the old label. I'm sharing a picture of the output I'm getting.
I know about the method w.delete('all')
however, after using it my python is crashing. Can someone please suggest how can I modify it to erase completely?
or
operator however my python is getting crashed. Right now, I able to exit only upon pressing the enter key. If I press another button, python is getting crashed.
Can I please know the reason my python is crashing?My code is:
import tkinter as tk
import msvcrt
import random
root= tk.Tk()
myCanvas = tk.Canvas(root, width = 500, height = 200)
myCanvas.pack()
w = tk.Canvas(root, width = 500, height = 200)
w.place(relx= 0.5, rely=0.1)
def printing_2():
flag2=1
name_list=['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']
input1 = msvcrt.getwch()
label2 = tk.Label(root, font=('Courier', 15))
w.create_window(60, 40, window=label2)
if flag1!=1 or input1!='\r':
label2.config(text=random.choice(name_list))
root.after(10, printing_2)
def printing_1():
flag1=1
name_list=['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']
input1 = msvcrt.getwch()
if flag2!=1 or input1!='\r':
label2 = tk.Label(root, text=random.choice(name_list), font=('Courier', 15))
w.create_window(60, 40, window=label2)
root.after(10, printing_1)
flag1=0
flag2=0
B1 = tk.Button(root, text ="Option 1", font=('Courier', 12), command= printing_1)
myCanvas.create_window(40, 30, window=B1)
B2 = tk.Button(root, text ="Option 2", font=('Courier', 12), command= printing_2)
myCanvas.create_window(40, 80, window=B2)
root.mainloop()
You should create empty label at start and later only change text in existing label
label2.config(text=random.choice(name_list))
or
label2["text"] = random.choice(name_list))
When you press button then you could run function which change both values flag1
and flag2
(one set True
and other set False
) and after that run function which will run loop using after()
And you have to use global
to set external variables. Without global
you create local variables.
You could use more readable names running_1
, running_2
instead of flag1
, flag2
and use values True/False
instead of 0/1
And instead of msvcrt
you can use root.bind("<Return>", stop)
to run function stop()
which will set running_1 = False
and running_2 = False
to stop all loop.s
Minimal working code
BTW: I use 500
in after()
to slowdown it and see what values it displays.
import tkinter as tk
import random
# --- functions
def printing_1():
global running_1
global running_2
global name_list
running_1 = True
running_2 = False # stop other list
name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']
print("start list 1")
update_1()
def update_1():
if running_1:
label["text"] = random.choice(name_list)
root.after(500, update_1)
def printing_2():
global running_1
global running_2
global name_list
running_1 = False # stop other list
running_2 = True
name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']
print("start list 2")
update_2()
def update_2():
if running_2:
label["text"] = random.choice(name_list)
root.after(500, update_2)
def stop(event):
global running_1
global running_2
running_1 = False
running_2 = False
print('stoped')
# --- main ---
running_1 = False
running_2 = False
name_list = None
root = tk.Tk()
root.bind('<Return>', stop)
canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()
w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)
label = tk.Label(root)
w.create_window(60, 40, window=label)
button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)
button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)
root.mainloop()
EDIT:
You can also reduce to use only one running
and one function update_label()
.
I check if running
is True
then I don't run new loop but it will automatically use already running loop but with new name_list
import tkinter as tk
import random
# --- functions
def printing_1():
global name_list
global running
name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']
if not running:
running = True
update_label()
def printing_2():
global name_list
global running
name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']
if not running:
running = True
update_label()
def update_label():
if running:
label["text"] = random.choice(name_list)
root.after(500, update_label)
def stop(event):
global running
running = False
print('stoped')
# --- main ---
name_list = None
running = False
root = tk.Tk()
root.bind('<Return>', stop)
canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()
w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)
label = tk.Label(root)
w.create_window(60, 40, window=label)
button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)
button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)
root.mainloop()
EDIT:
If you want to update label only when when you press key then you don't need msvcrt
and after
but only bind('<Key>', function_name)
import tkinter as tk
import random
# --- functions
def printing_1():
"""Assign new list and update label"""
global name_list
name_list = ['Rui Sagar' , 'Nana Kana', 'Mike', 'Bob', 'Drake']
# set value at start
update_label()
def printing_2():
"""Assign new list and update label"""
global name_list
name_list = ['Mia Jennete Moi' , 'cara', 'juili', 'meera', 'ed']
# set value at start
update_label()
def on_key(event):
"""Update label if list is assigned to `name_list`
and pressed key is different then `Return`"""
if name_list and event.keysym != 'Return':
update_label()
def update_label():
label["text"] = random.choice(name_list)
# --- main ---
name_list = None
root = tk.Tk()
root.bind('<Key>', on_key) # run function when pressed any key
canvas = tk.Canvas(root, width=500, height=200)
canvas.pack()
w = tk.Canvas(root, width=500, height=200)
w.place(relx=0.5, rely=0.1)
label = tk.Label(root)
w.create_window(60, 40, window=label)
button1 = tk.Button(root, text="Option 1", command=printing_1)
canvas.create_window(40, 30, window=button1)
button2 = tk.Button(root, text="Option 2", command=printing_2)
canvas.create_window(40, 80, window=button2)
root.mainloop()