Dov*_*ova 6 python tkinter tkinter-canvas
尝试在tkinter中进行简单的移动:
import tkinter as tk
class GameApp(object):
"""
An object for the game window.
Attributes:
master: Main window tied to the application
canvas: The canvas of this window
"""
def __init__(self, master):
"""
Initialize the window and canvas of the game.
"""
self.master = master
self.master.title = "Game"
self.master.geometry('{}x{}'.format(500, 500))
self.canvas = tk.Canvas(self.master)
self.canvas.pack(side="top", fill="both", expand=True)
self.start_game()
#----------------------------------------------#
def start_game(self):
"""
Actual loading of the game.
"""
player = Player(self)
#----------------------------------------------#
#----------------------------------------------#
class Player(object):
"""
The player of the game.
Attributes:
color: color of sprite (string)
dimensions: dimensions of the sprite (array)
canvas: the canvas of this sprite (object)
window: the actual game window object (object)
momentum: how fast the object is moving (array)
"""
def __init__(self, window):
self.color = ""
self.dimensions = [225, 225, 275, 275]
self.window = window
self.properties()
#----------------------------------------------#
def properties(self):
"""
Establish the properties of the player.
"""
self.color = "blue"
self.momentum = [5, 0]
self.draw()
self.mom_calc()
#----------------------------------------------#
def draw(self):
"""
Draw the sprite.
"""
self.sprite = self.window.canvas.create_rectangle(*self.dimensions, fill=self.color, outline=self.color)
#----------------------------------------------#
def mom_calc(self):
"""
Calculate the actual momentum of the thing
"""
self.window.canvas.move(self.sprite, *self.momentum)
self.window.master.after(2, self.mom_calc)
#----------------------------------------------#
#----------------------------------------------#
root = tk.Tk()
game_window = GameApp(root)
Run Code Online (Sandbox Code Playgroud)
其中self.momentum为含2个整数的数组:一个用于x运动,和另一个用于y运动.然而,矩形的实际移动非常慢(每秒约5次移动),self.window.master.after()时间似乎没有效果.
以前在另一个tkinter项目中,我设法得到了非常敏感的tkinter运动,所以我只是想知道是否有一种方法可以在这种情况下最小化运动更新时间,通过使用不同风格的OOP,或只是不同的代码共.
更新:关闭.after()方法中的时间确实很重要,它实际上堆叠到方法的实时.使用timeit时间调用方法后,我得到了这个输出:
>>> print(timeit.timeit("(self.window.master.after(2, self.mom_calc))", number=10000, globals={"self":self}))
0.5395521819053108
Run Code Online (Sandbox Code Playgroud)
所以我想真正的问题是:为什么这种.after()方法需要这么长时间?
更新2:在多台计算机上测试,任何平台上的移动速度仍然很慢.
我至少没有看到您在使用 Python 3.6 的 Windows 10 上报告的问题。我测试了如图所示的程序,并且必须root.mainloop()在末尾添加一个。这没有显示矩形,因为对象离开画布的速度太快而无法看到。
所以我修改了它以在墙壁之间弹跳并添加一个计数器来打印数量mom_calc每秒的调用次数。将后超时设置为 20 毫秒后,我每秒收到 50 个动作调用,正如预期的那样。将其设置为 2ms,如您的帖子中所示,我每秒得到大约 425 毫秒,因此这里有一点错误,每次调用大约需要 2.3 或 2.4 毫秒。这是一个有点变量,因为其他进程可能会在此粒度上占用一些时间。
这是(稍微)修改的代码:
import tkinter as tk
class GameApp(object):
"""
An object for the game window.
Attributes:
master: Main window tied to the application
canvas: The canvas of this window
"""
def __init__(self, master):
"""
Initialize the window and canvas of the game.
"""
self.master = master
self.master.title = "Game"
self.master.geometry('{}x{}'.format(500, 500))
self.canvas = tk.Canvas(self.master, background="white")
self.canvas.pack(side="top", fill="both", expand=True)
self.start_game()
#----------------------------------------------#
def start_game(self):
"""
Actual loading of the game.
"""
player = Player(self)
#----------------------------------------------#
#----------------------------------------------#
class Player(object):
"""
The player of the game.
Attributes:
color: color of sprite (string)
dimensions: dimensions of the sprite (array)
canvas: the canvas of this sprite (object)
window: the actual game window object (object)
momentum: how fast the object is moving (array)
"""
def __init__(self, window):
self.color = ""
self.dimensions = [225, 225, 275, 275]
self.window = window
self.movement = 0
self.movement_last = 0
self.properties()
#----------------------------------------------#
def properties(self):
"""
Establish the properties of the player.
"""
self.color = "blue"
self.momentum = [5, 0]
self.draw()
self.mom_calc()
self.velocity()
#----------------------------------------------#
def draw(self):
"""
Draw the sprite.
"""
self.sprite = self.window.canvas.create_rectangle(*self.dimensions, fill=self.color, outline=self.color)
#----------------------------------------------#
def mom_calc(self):
"""
Calculate the actual momentum of the thing
"""
pos = self.window.canvas.coords(self.sprite)
if pos[2] > 500:
self.momentum = [-5, 0]
elif pos[0] < 2:
self.momentum = [5, 0]
self.window.canvas.move(self.sprite, *self.momentum)
self.window.master.after(2, self.mom_calc)
self.movement = self.movement + 1
def velocity(self):
print(self.movement - self.movement_last)
self.movement_last = self.movement
self.aid_velocity = self.window.master.after(1000, self.velocity)
#----------------------------------------------#
#----------------------------------------------#
if __name__ == '__main__':
root = tk.Tk()
game_window = GameApp(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)