简体   繁体   English

在Python中的Tkinter窗口之外获取鼠标事件

[英]Get mouse events outside of Tkinter window in Python

I am writing a program that connects to design software, like an external plugin, then monitors mouse movement and events. 我正在编写一个程序,该程序连接到设计软件,例如外部插件,然后监视鼠标的移动和事件。 It will take actions based on to the state of the connected software mouse events. 它将根据连接的软件鼠标事件的状态采取措施。

The idea is the external application will have the capability to interface to multiple similar programs instead of program specific plugins. 想法是外部应用程序将具有与多个类似程序(而不是程序特定的插件)接口的能力。

The prototype, and potentially the production software, is being written in python using the Tkinter GUI library. 使用Tkinter GUI库以python编写了原型以及可能的生产软件。 The attempt is to make it simple and portable. 尝试是使其简单和可移植。

I was easily able to grab "OS" level mouse position (true screen X,Y) without the Tkinter window needing to be active. 我很容易就能抓住“ OS”级别的鼠标位置(真实屏幕X,Y),而无需激活Tkinter窗口。 My issue is that I am not finding a way to easily get the mouse click events from Tkinter. 我的问题是我没有找到一种方法来轻松地从Tkinter获取鼠标单击事件。 I can only gather events when over the active Tkinter window. 我只能在活动的Tkinter窗口上收集事件。

Tkinter provides this for mouse position: Tkinter为鼠标位置提供了此功能:

coord = self.gui.winfo_pointerxy()

I cannot find similar for mouse events. 我找不到类似的鼠标事件。 There are libraries like selfspy and Pymouse (now part of PyUserInput) that monitor events, but are mainly for control of the input devices. 有一些诸如selfspyPymouse (现在是PyUserInput的一部分)的库可以监视事件,但是主要用于控制输入设备。 My backup idea is to use these libraries for reference on writing my own input monitoring program. 我的备份想法是在编写我自己的输入监视程序时使用这些库作为参考。

My two main platforms are Mac and Windows. 我的两个主要平台是Mac和Windows。

Long story short: 长话短说:

  • Can Tkinter give me mouse events when the events are outside the Tkinter window. 当事件在Tkinter窗口之外时,Tkinter可以给我鼠标事件吗?
  • If not, are there other options "out of the box" that can give me mouse X,Y and mouse events. 如果没有,还有“开箱即用”的其他选项可以给我鼠标X,Y和鼠标事件。
  • If there are no out of the box solutions, some recommendation on approach and API. 如果没有现成的解决方案,请对方法和API提出一些建议。 (looks like win32api for windows, Quartz and/or Cocoa in Mac and Xlib in Linux) (在Windows中看起来像win32api,在Mac中看起来像是Quartz和/或Cocoa,在Linux中看起来像是Xlib)

Thanks for your time 谢谢你的时间

This way you get the mouse position with TKinter . 这样,您可以使用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()

There is a cross-platform module pyautogui (works for os x, windows, linux). 有一个跨平台的模块pyautogui(适用于OS X,Windows和Linux)。

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

refer to this article how to detect the mouse clicks for windows 参考本文如何检测Windows的鼠标单击

On Mac, the easiest option is probably NSEvent 's addGlobalMonitorForEventsMatchingMask:handler: : https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/occ/clm/NSEvent/addGlobalMonitorForEventsMatchingMask:handler : 在Mac上,最简单的选项可能是NSEventaddGlobalMonitorForEventsMatchingMask:handler: :: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/occ/clm / NSEvent / addGlobalMonitorForEventsMatchingMask:handler

Note that this is specifically for events sent to other applications, and not your own. 请注意,这专门用于发送给其他应用程序的事件,而不是您自己的事件。

On a lower level, you can also look into using Quartz event taps. 在较低级别,您也可以使用Quartz事件水龙头。 Simple example using PyObjC: 使用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

(I'm afraid I can't comment in detail regarding a Windows solution.) (恐怕我无法对Windows解决方案进行详细评论。)

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

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