Reputation: 12847
My canvas shows a grid of rectangles in randomly changing colors, but when I want it to end, it does not show the "Bye Bye!" message I added to the canvas. Why is that?
Even if I comment the lines for i in ...
inside the __init__
(i.e. the for loop that creates the rectangles in the first place) I don't see the text.
The text update is done in the start of "update" function, after max iterations.
when changing to self.canvas.create_text(100,100, text="Bye Bye!")
, it does seem to work... but only when no rectangles are showing
import tkinter as tk
from time import sleep
import random
class GUI:
def __init__(self, rows = 10, cols = 10, iteration_timer = 1):
self.canv_w = 300
self.canv_h = 300
self.cell_w = self.canv_w // cols
self.cell_h = self.canv_h // rows
self.master = tk.Tk()
self.canvas = tk.Canvas(self.master, width = self.canv_w, height = self.canv_h)
self.canvas.pack()
self.rect_dict = {}
self.iteration_timer = iteration_timer
self.iterations = 0
self.MAX_ITER = 10
for r in range(rows):
for c in range(cols):
self.rect_dict[(r*self.cell_h, c*self.cell_w)] = self.canvas.create_rectangle(r *self.cell_h, c *self.cell_w,
(1+r)*self.cell_h, (1+c)*self.cell_w,
fill="blue")
self.master.after(iteration_timer, self.update)
tk.mainloop()
def update(self):
if self.iterations >= self.MAX_ITER:
self.canvas.create_text(0,0,fill="darkblue", font="Times 100 italic bold", text="Bye Bye!")
sleep(2)
self.canvas.delete(tk.ALL)
self.master.destroy()
return
self.iterations += 1
for k in self.rect_dict:
r = self.rect_dict[k]
c = random.choice(['yellow', 'red', 'black', 'blue' , 'white'])
self.canvas.itemconfig(r, fill=c)
# call again
self.master.after(self.iteration_timer, self.update)
def main():
gui = GUI(rows = 20, cols = 20)
if __name__ == "__main__":
main()
Upvotes: 0
Views: 248
Reputation: 10602
When you use time.sleep
, everything including the Tkinter mainloop halts. The Tkinter mainloop is responsible for updating the UI, so as long as you don't return to the mainloop you won't see any updates to the UI unless you update it manually. Because you destroy the UI right after the sleep
, you never see the updated UI with the text.
There's basically two thing you can do, either update manually before calling sleep
, or changing the sleep
call to after
, which returns to the mainloop and schedules the function you pass to it.
To update manually call self.master.update()
right before sleep
.
To replace the sleep
with after
, just change
sleep(2)
self.canvas.delete(tk.ALL)
self.master.destroy()
to
self.master.after(2000, self.master.destroy)
Upvotes: 3