Tkinter only calls after_idle once

后端 未结 2 538
离开以前
离开以前 2020-12-18 03:01

I am new to Tkinter, so I apologize if this is easy, but I have search for a couple of hours and can\'t figure it out. What I want to do is after the mainloop is idle, I al

2条回答
  •  猫巷女王i
    2020-12-18 03:49

    @user1763510, notice that in Bryan Oakley's answer, he has checkForGroupUpdates call self.after again. This is because self.after only does a single call, so getting repeated calls requires having it call itself within the function that gets called by the first call. This way, it keeps repeatedly calling itself.

    The same goes for the after_idle() function. You have to have checkForGroupUpdates call after_idle() again at the bottom.

    Here is the documentation for after, after_idle, etc. There is even a little example in the after description, which makes it all clear.

    Documentation: http://effbot.org/tkinterbook/widget.htm

    Example from link above, under the afterdescription:

    #Method 1
    class App:
        def __init__(self, master):
            self.master = master
            self.poll() # start polling
    
        def poll(self):
            ... do something ...
            self.master.after(100, self.poll)
    

    To use after_idle instead, it would look like this:

    #Method 2
    class App:
        def __init__(self, master):
            self.master = master
            self.poll() # start polling
    
        def poll(self):
            ... do something ...
            self.master.update_idletasks()
            self.master.after_idle(self.poll)
    

    Notice the addition of the self.master.update_idletasks() line. This draws the GUI and handles button presses and things. Otherwise, after_idle() will suck up all resources and not let the GUI self-update properly in the mainloop().

    An alternative to using

            self.master.update_idletasks()
            self.master.after_idle(self.poll)
    

    is to use:

            #Method 3
            self.master.update_idletasks()
            self.master.after(0, self.poll)
    

    Using self.master.after(0, self.poll) is my preferred technique, as it allows me to easily change the 0 to something else if I decide I don't need to run self.poll constantly. By increasing the delay time to at least 1 ms, you no longer need to call self.master.update_idletasks() at all. So, this works too:

            #Method 4
            self.master.after(1, self.poll)
    

    Also notice that for all examples above, calling self.poll() in the __init__ function is what kicks it all off, and storing master into self.master is necessary simply so that inside poll you can call the after or after_idle function via self.master.after_idle, for example.

    Q: Is this stable/does it work?
    A: I ran a test code using Method 3 just above for ~21 hrs, and it ran stably the whole time, allowing the GUI to be usable and all.

    Q: What is the speed comparison for each method above?
    A:

    • Method 1: (I didn't speed test it)
    • Method 2: ~0.44 ms/iteration
    • Method 3: ~0.44 ms/iteration
    • Method 4: ~1.61 ms/iteration

    Q: Which is my preferred method?
    A: Method 3 or 4.

提交回复
热议问题