Henrik Oldcorn
Henrik Oldcorn

Reputation: 144

Continually running functions in tkinter after mainloop in Python 3.4

What I want to do is colour in a single pixel in the centre of the screen, then at random choose an adjacent pixel and colour it in, and then repeat until some condition is met - anything such as time, or the screen is full, or after a certain number of pixels are full. This ending isn't too important, I haven't got that far yet, and I think I could manage to work that out myself.

I have no experience with tkinter, but I decided it was the best way to display this, since I don't really no any other way. Some of this code (mainly the tkinter functions like Canvas, PhotoImage etc) is therefore copy-pasted (and slightly edited) from examples I found here.

What my code does when run is hard to tell - it uses the CPU as much as it can seemingly indefinitely, and slowly increases its memory usage, but doesn't appear to do anything. No window opens, and the IDLE interpreter goes to a blank line, as usual when calculating something. When killed, the window opens, and displays a white page with a little black blob in the bottom right corner - as if the program had done what it was meant to, but without showing it happening, and starting in the wrong place.

So:

Upvotes: 1

Views: 1955

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385910

The pattern for running something periodically in tkinter is to write a function that does whatever you want it to do, and then the last thing it does is use after to call itself again in the future. It looks something like this:

import tkinter as tk
...

class Example(...):
    def __init__(self, ...):
        ...
        self.canvas = tk.Canvas(...)
        self.delay = 100 # 100ms equals ten times a second
        ...
        # draw the first thing
        self.draw_something()

    def draw_something(self):
        <put your code to draw one thing here>
        self.canvas.after(self.delay, self.draw_something)

After the function draws something, it schedules itself to run again in the future. The delay defines approximately how long to wait before the next call. The smaller the number, the faster it runs but the more CPU it uses. This works, because between the time after is called and the time elapses, the event loop (mainloop) is free to handle other events such as screen redraws.

While you may think this looks like recursion, it isn't since it's not making a recursive call. It's merely adding a job to a queue that the mainloop periodically checks.

Upvotes: 2

Related Questions