繁体   English   中英

如何在 tkinter 窗口中设置鼠标位置

[英]How can I set the mouse position in a tkinter window

我有一个 3d 渲染程序,它根据鼠标在屏幕上的位置围绕观察者旋转世界。 世界旋转的弧度量由这条线定义

    glob.worldx=-(w.winfo_pointerxy()[0]-xy[0])/250

其中xy[0]是屏幕中心的x坐标

这意味着观察者视野可以旋转的量受鼠标可以移动的距离的限制。 如果我能让鼠标回到屏幕中央,我就可以解决这个问题。 有任何想法吗?

好消息是有办法做到这一点。

中间消息是它没有很好的记录。

坏消息是它仅适用于某些平台。

另一个中间消息是,您至少可以在某些平台上超越 Tk。


在 Tcl/Tk 中执行此操作的方法是使用-warp 1生成<Motion>事件。 这方面的文档很少,并且分散在几个不同的页面(从bind开始),但这里描述了详细信息。 基本上,就是这样:

event generate . <Motion> -warp 1 -x 50 -y 50

那么,你如何从 Tkinter 做到这一点?

好吧, 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 认为光标移动了。


从浏览各种论坛,它看起来像:

  • 麦克:不起作用。
  • Windows:通常有效。
    • 您必须拥有 Tk 8.4.something 或更高版本。 我找不到这方面的错误,但是您可以依靠任何官方 Windows 二进制安装的 Python 2.7 或 3.x+ 来使用 8.4。
    • 您也不得运行全屏应用程序(使用 Tk,您通常不会运行)。
    • 在 Vista 及更高版本上,在某些情况下它不起作用。 这可能与不拥有桌面会话或不是本地控制台会话有关,或者可能与需要管理员或其他权限有关。
    • 如果它不起作用,很容易直接转到 Win32 API。
  • X11(大多数 linux、*BSD 等):通常
    • 您的窗口管理器不得禁止其他客户端扭曲指针。 幸运的是,这似乎并不常见。
    • 如果你有这个问题,那就没有办法了。
  • 其他平台(iOS、Android 等):不知道。

对于 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))

对于任何有兴趣将光标移动到屏幕上的绝对位置的人(使用@abernert 的 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 窗口。 请注意,此函数会创建一个刷新两次的新窗口,因此它可能会很慢并且用户可能会注意到创建的窗口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM