我有一个3D渲染程序,它根据鼠标在屏幕上的位置使世界围绕观察者旋转。世界旋转的弧度量由以下代码定义:
glob.worldx=-(w.winfo_pointerxy()[0]-xy[0])/250
其中 xy[0] 是屏幕中心的 x 坐标
这意味着观察者可以旋转视野的量受到鼠标移动距离的限制。如果我能让鼠标回到屏幕中心,就可以解决这个问题了。有什么想法吗?
我有一个3D渲染程序,它根据鼠标在屏幕上的位置使世界围绕观察者旋转。世界旋转的弧度量由以下代码定义:
glob.worldx=-(w.winfo_pointerxy()[0]-xy[0])/250
其中 xy[0] 是屏幕中心的 x 坐标
这意味着观察者可以旋转视野的量受到鼠标移动距离的限制。如果我能让鼠标回到屏幕中心,就可以解决这个问题了。有什么想法吗?
<Motion>
事件,并使用-warp 1
参数。关于此的文档较少,分散在几个不同的页面上(从bind
开始),但详细信息在here中描述。基本上就是这样:event generate . <Motion> -warp 1 -x 50 -y 50
event_generate
没有任何文档说明,<Motion>
事件和warp
参数也是如此...但是如果您知道Tk映射到Tkinter的方式,那么很容易弄清楚:window.event_generate('<Motion>', warp=True, x=50, y=50)
这确实会生成一个事件,你可以通过绑定<Motion>
来观察到。下面是一个简单的测试程序:
from tkinter import *
root = Tk()
def key(event):
root.event_generate('<Motion>', warp=True, x=50, y=50)
def motion(event):
print('motion {}, {}'.format(event.x, event.y))
root.bind('<Key>', key)
root.bind('<Motion>', motion)
root.mainloop()
运行它,点击窗口以确保它有焦点,移动光标,你会看到它打印出类似这样的东西:
motion 65, 69
motion 65, 70
motion 65, 71
motion 50, 50
这很好…但是它可能实际上不能移动您的光标,如果是这样,所有这些只是欺骗Tk认为光标已经移动了。
对于Mac,您想生成并发送一个NSMouseMoved
事件。简单的方法是使用pyobjc
(如果您使用的是Apple的Python,则内置;否则您必须安装它):
app = Foundation.NSApplication.sharedApplication()
event = Foundation.NSEvent.mouseEventWithType_location_modifierFlags_timestamp_windowNumber_context_eventNumber_clickCount_pressure_(
Foundation.NSMouseMoved, (50, 50), 0, 0,
app.mainWindow().windowNumber(), None, 0, 0, 0.0)
app.sendEvent_(event)
对于Windows系统,你需要调用SetCursorPos
API或生成并发送MOUSEEVENT。前者可能无法在DirectX游戏中使用;后者可能无法在远程桌面上使用。针对这种情况,你可能想要使用前者。无论哪种方式,最简单的方法是安装pywin32
,然后只需执行以下操作:
win32api.SetCursorPos((50, 50))
event_generate
函数;我只是将其绑定到<Key>
以便轻松测试。很高兴它对你起作用了。 - abarnert对于任何想要将光标移动到屏幕上绝对位置的人(使用@abarnert的tkinter方法):
# Moves the mouse to an absolute location on the screen
def move_mouse_to(x, y):
# Create a new temporary root
temp_root = tk.Tk()
# Move it to +0+0 and remove the title bar
temp_root.overrideredirect(True)
# Make sure the window appears on the screen and handles the `overrideredirect`
temp_root.update()
# Generate the event as @abarnert did
temp_root.event_generate("<Motion>", warp=True, x=x, y=y)
# Make sure that tcl handles the event
temp_root.update()
# Destroy the root
temp_root.destroy()
这个函数不应该干扰其他的tkinter窗口。请注意,这个函数会创建一个新的窗口并进行两次刷新,因此可能会比较慢,用户可能会注意到新创建的窗口。