【问题标题】:Get mouse events outside of Tkinter window in Python在 Python 中获取 Tkinter 窗口之外的鼠标事件
【发布时间】:2015-12-22 19:04:23
【问题描述】:

我正在编写一个连接到设计软件的程序,例如外部插件,然后监视鼠标移动和事件。它将根据连接的软件鼠标事件的状态采取行动。

这个想法是外部应用程序将能够与多个类似程序而不是特定于程序的插件接口。

原型和可能的生产软件是使用 Tkinter GUI 库用 python 编写的。尝试是使其简单和便携。

无需激活 Tkinter 窗口,我就能轻松获取“OS”级别的鼠标位置(真正的屏幕 X、Y)。我的问题是我没有找到一种方法来轻松地从 Tkinter 获取鼠标单击事件。我只能在活动的 Tkinter 窗口上收集事件。

Tkinter 为鼠标位置提供了这个:

coord = self.gui.winfo_pointerxy()

我找不到类似的鼠标事件。有像 selfspyPymouse(现在是 PyUserInput 的一部分)这样的库来监视事件,但主要用于控制输入设备。我的备用想法是在编写我自己的输入监控程序时使用这些库作为参考。

我的两个主要平台是 Mac 和 Windows。

长话短说:

  • Tkinter 能否在事件超出范围时给我鼠标事件 Tkinter 窗口。
  • 如果没有,是否还有其他“开箱即用”选项可以为我提供鼠标 X、Y 和鼠标事件。
  • 如果没有开箱即用的解决方案,关于方法和 API 的一些建议。 (看起来像 windows、Quartz 和/或的 win32api Mac 中的 Cocoa 和 Linux 中的 Xlib)

感谢您的宝贵时间

【问题讨论】:

    标签: python windows macos tkinter mouse


    【解决方案1】:

    这样您就可以通过 TKinter 获得鼠标位置。

    import Tkinter as tk
    root = tk.Tk()
    
    def motion(event):
        x, y = event.x, event.y
        print('{}, {}'.format(x, y))
    
    root.bind('<Motion>', motion)
    root.mainloop()
    

    有一个跨平台模块pyautogui(适用于os x、windows、linux)。

    pyautogui.posistion() //returns tuple with mouse x and y values
                          // same for python 3.x
    

    参考这个article如何检测windows的鼠标点击

    【讨论】:

    • 感谢您的发帖。这似乎对鼠标位置和移动很有帮助,但是这些 API 是否也可以使用应用程序窗口外的按钮/单击事件?我能想到的最简单的示例功能类型是我需要在应用程序窗口之外单击并拖动的屏幕截图应用程序。您需要能够看到鼠标点击以及鼠标移动/位置。
    • 除了寡妇,我认为没有任何方法可以在窗口外获取鼠标点击事件。
    【解决方案2】:

    在 Mac 上,最简单的选择可能是 NSEventaddGlobalMonitorForEventsMatchingMask:handler::https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/occ/clm/NSEvent/addGlobalMonitorForEventsMatchingMask:handler:

    请注意,这是专门针对发送到其他应用程序的事件,而不是您自己的。

    在较低级别上,您还可以研究使用 Quartz 事件点击。使用 PyObjC 的简单示例:

    from Quartz import CGEventTapCreate
    # ...etc.
    
    def listen_for_mouse_events():
      mouse_tap = CGEventTapCreate(
        kCGSessionEventTap,
        kCGHeadInsertEventTap,
        kCGEventTapOptionListenOnly,
        CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp),
        on_mouse_event,
        None
        )
      runLoopSource = CFMachPortCreateRunLoopSource(None, mouse_tap, 0)
      CFRunLoopAddSource(
        CFRunLoopGetCurrent(),
        runLoopSource,
        kCFRunLoopDefaultMode
      )
      CGEventTapEnable(mouse_tap, True)
    
    def on_mouse_event(proxy, event_type, event, refcon):
      location = CGEventGetLocation(event)
      if (event_type == kCGEventLeftMouseDown):
        pass
      elif (event_type == kCGEventLeftMouseUp):
        pass
    

    (恐怕我无法详细评论 Windows 解决方案。)

    【讨论】:

    • 完全跑题了!问题是“在 TKINTER 窗口之外!”如果我不不喜欢这个动作,我会否决你。
    猜你喜欢
    • 2012-11-23
    • 1970-01-01
    • 2011-01-07
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多