Tkinter understanding after()

半腔热情 提交于 2019-12-21 17:37:10

问题


First of all, take a look at my previous thread here: Tkinter understanding mainloop

After following the advice from there, in GUI programming, infinite loops have to be avoided at all costs, in order to keep the widgets responsive to user input.

Instead of using:

while 1:
    ball.draw()
    root.update()
    time.sleep(0.01)

I managed using self.canvas.after(1, self.draw) inside my draw() function.

So my code now looks like this:

# Testing skills in game programming

from Tkinter import *

root = Tk()
root.title("Python game testing")
root.resizable(0, 0)
root.wm_attributes("-topmost", 1)

canvas = Canvas(root, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
root.update()

class Ball:
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
        self.canvas.move(self.id, 245, 100)

        self.canvas_height = canvas.winfo_height()
        self.x = 0
        self.y = -1

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)

        pos = self.canvas.coords(self.id)
        if pos[1] <= 0:
            self.y = 1
        if pos[3] >= self.canvas_height:
            self.y = -1

        self.canvas.after(2, self.draw)


ball = Ball(canvas, "red")
ball.draw()

root.mainloop()

However, time inside self.canvas.after() does not work properly... If set to 1 it's extremely fast! If it's set to 10, 5 or even 2, it's too slow! I didn't have that problem while using the above while loop in my code since the time.sleep() worked as it should!


EDIT:

I can now report that the time inside the after function of Tkinter does not work properly in my Windows 8.1 tablet, and in my Windows 8.1 laptop, while in the same laptop when running Ubuntu through virtual machine it does work as it should.


回答1:


Time in time.sleep is in seconds whereas in after() it is in milliseconds. time.sleep(0.01) is the same as self.canvas.after(10, self.draw). If after(2, func) was too slow but after(1, func) was too fast then you could try sleep(0.0005) then after(1, func) do give a delay of 1.5 milliseconds but it is barely noticeable. Either way, fiddle with the timing until the pause is right.




回答2:


Speed of the object (canvas) and clock/loop speed should be considered as two different things, IMHO. Hence, you can leave loop after 2ms or even larger like 10...25...

...
self.canvas.after(2, self.draw)
... # loop this after 2 ms.

while, changing speed in terms of 'how many pixels' :

pos = self.canvas.coords(self.id)
    if pos[1] <= 0:
        self.y = 20
    if pos[3] >= self.canvas_height:
        self.y = -20

so adjusting these values, and :

self.canvas.move(self.id, 245, 100)

can let you fine-tune position and speed of your red dot. Hope it helps



来源:https://stackoverflow.com/questions/29176212/tkinter-understanding-after

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!