CIsForCookies
CIsForCookies

Reputation: 12847

canvas not showing text

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

Answers (1)

fhdrsdg
fhdrsdg

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

Related Questions