简体   繁体   中英

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. 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. My issue is that I am not finding a way to easily get the mouse click events from Tkinter. I can only gather events when over the active Tkinter window.

Tkinter provides this for mouse position:

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. 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.

Long story short:

  • Can Tkinter give me mouse events when the events are outside the Tkinter window.
  • If not, are there other options "out of the box" that can give me mouse X,Y and mouse events.
  • If there are no out of the box solutions, some recommendation on approach and API. (looks like win32api for windows, Quartz and/or Cocoa in Mac and Xlib in Linux)

Thanks for your time

This way you get the mouse position with 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.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

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 :

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. Simple example using 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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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