tkinter 中的事件处理与 pygame 中的不同,因此与其直接等效于 mouse.get_rel(),不如创建一个在每次鼠标移动时调用回调函数的东西(这是绑定到'<Motion>' 事件完成)。为了帮助做到这一点,定义了一个RelativeMotion 类来隐藏和封装尽可能多的混乱细节。下面是它运行的截图。
import tkinter as tk
class RelativeMotion(object):
""" Relative mouse motion controller. """
def __init__(self, callback):
self.__call__ = self._init_location # first call
self.callback = callback
def __call__(self, *args, **kwargs):
# Implicit invocations of special methods resolve to instance's type.
self.__call__(*args, **kwargs) # redirect call to instance itself
def _init_location(self, event):
self.x, self.y = event.x, event.y # initialize current position
self.__call__ = self._update_location # change for any subsequent calls
def _update_location(self, event):
dx, dy = event.x-self.x, event.y-self.y
self.x, self.y = event.x, event.y
self.callback(dx, dy)
class Application(tk.Frame): # usage demo
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
self.relative_motion = RelativeMotion(self.canvas_mouse_motion)
self.canvas.bind('<Motion>', self.relative_motion) # when over canvas
def createWidgets(self):
self.motion_str = tk.StringVar()
self.canvas_mouse_motion(0, 0) # initialize motion_str text
label_width = len(self.motion_str.get())
self.motion_lbl = tk.Label(self, bg='white', width=label_width,
textvariable=self.motion_str)
self.motion_lbl.grid(row=0, column=0)
self.quit_btn = tk.Button(self, text='Quit', command=self.quit)
self.quit_btn.grid(row=1, column=0)
self.canvas = tk.Canvas(self, width='2i', height='2i', bg='white')
self.canvas.grid(row=1, column=1)
def canvas_mouse_motion(self, dx, dy):
self.motion_str.set('{:3d}, {:3d}'.format(dx, dy))
app = Application()
app.master.title('Relative Motion Demo')
app.mainloop()
跑步