English 中文(简体)
如何使用Python控制Mac中的鼠标?
原标题:
  • 时间:2008-11-11 15:04:43
  •  标签:

在OS X上,使用Python移动鼠标(可能还要点击)的最简单方法是什么?

这只是为了快速原型制作,没必要讲究。

最佳回答

我挖掘了 Synergy 的源代码,找到了生成鼠标事件的调用。

#include <ApplicationServices/ApplicationServices.h>

int to(int x, int y)
{
    CGPoint newloc;
    CGEventRef eventRef;
    newloc.x = x;
    newloc.y = y;

    eventRef = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, newloc,
                                        kCGMouseButtonCenter);
    //Apparently, a bug in xcode requires this next line
    CGEventSetType(eventRef, kCGEventMouseMoved);
    CGEventPost(kCGSessionEventTap, eventRef);
    CFRelease(eventRef);

    return 0;
}

现在开始编写Python绑定!

问题回答

请在此页面上尝试这段代码。它定义了两个函数mousemovemouseclick,它们钩入了苹果的Python集成和平台的Quartz库之间的连接。

这段代码适用于10.6,在10.7上我使用它。这段代码的好处是它能够生成鼠标事件,而一些其他解决方案则不能。我使用它来发送鼠标事件到BBC iPlayer中已知的按钮位置,以控制它们的Flash播放器(非常脆弱)。特别是鼠标移动事件是必需的,否则Flash播放器永远不会隐藏鼠标光标。像CGWarpMouseCursorPosition这样的函数无法实现这一点。

from Quartz.CoreGraphics import CGEventCreateMouseEvent
from Quartz.CoreGraphics import CGEventPost
from Quartz.CoreGraphics import kCGEventMouseMoved
from Quartz.CoreGraphics import kCGEventLeftMouseDown
from Quartz.CoreGraphics import kCGEventLeftMouseUp
from Quartz.CoreGraphics import kCGMouseButtonLeft
from Quartz.CoreGraphics import kCGHIDEventTap

def mouseEvent(type, posx, posy):
        theEvent = CGEventCreateMouseEvent(
                    None, 
                    type, 
                    (posx,posy), 
                    kCGMouseButtonLeft)
        CGEventPost(kCGHIDEventTap, theEvent)

def mousemove(posx,posy):
        mouseEvent(kCGEventMouseMoved, posx,posy);

def mouseclick(posx,posy):
        # uncomment this line if you want to force the mouse 
        # to MOVE to the click location first (I found it was not necessary).
        #mouseEvent(kCGEventMouseMoved, posx,posy);
        mouseEvent(kCGEventLeftMouseDown, posx,posy);
        mouseEvent(kCGEventLeftMouseUp, posx,posy);

这是来自上面页面的代码示例:

##############################################################
#               Python OSX MouseClick
#       (c) 2010 Alex Assouline, GeekOrgy.com
##############################################################
import sys
try:
        xclick=intsys.argv1
        yclick=intsys.argv2
        try:
                delay=intsys.argv3
        except:
                delay=0
except:
        print "USAGE mouseclick [int x] [int y] [optional delay in seconds]"
        exit
print "mouse click at ", xclick, ",", yclick," in ", delay, "seconds"
# you only want to import the following after passing the parameters check above, because importing takes time, about 1.5s
# (why so long!, these libs must be huge : anyone have a fix for this ?? please let me know.)
import time
from Quartz.CoreGraphics import CGEventCreateMouseEvent
from Quartz.CoreGraphics import CGEventPost
from Quartz.CoreGraphics import kCGEventMouseMoved
from Quartz.CoreGraphics import kCGEventLeftMouseDown
from Quartz.CoreGraphics import kCGEventLeftMouseDown
from Quartz.CoreGraphics import kCGEventLeftMouseUp
from Quartz.CoreGraphics import kCGMouseButtonLeft
from Quartz.CoreGraphics import kCGHIDEventTap
def mouseEventtype, posx, posy:
        theEvent = CGEventCreateMouseEventNone, type, posx,posy, kCGMouseButtonLeft
        CGEventPostkCGHIDEventTap, theEvent
def mousemoveposx,posy:
        mouseEventkCGEventMouseMoved, posx,posy;
def mouseclickposx,posy:
        #mouseEvent(kCGEventMouseMoved, posx,posy); #uncomment this line if you want to force the mouse to MOVE to the click location first (i found it was not necesary).
        mouseEventkCGEventLeftMouseDown, posx,posy;
        mouseEventkCGEventLeftMouseUp, posx,posy;
time.sleepdelay;
mouseclickxclick, yclick;
print "done."

pynput库似乎是目前最好维护的库。它允许您控制和监视输入设备。

这是控制鼠标的例子:

from pynput.mouse import Button, Controller

mouse = Controller()

# Read pointer position
print( The current pointer position is {0} .format(
    mouse.position))

# Set pointer position
mouse.position = (10, 20)
print( Now we have moved it to {0} .format(
    mouse.position))

# Move pointer relative to current position
mouse.move(5, -5)

# Press and release
mouse.press(Button.left)
mouse.release(Button.left)

# Double click; this is different from pressing and releasing
# twice on Mac OSX
mouse.click(Button.left, 2)

# Scroll two steps down
mouse.scroll(0, 2)

最简单的方法是使用PyAutoGUI。

安装:

pip install pyautogui

例子:

  • 获取鼠标位置:

    >>> pyautogui.position()
    (187, 567)
    
  • 将鼠标移动到特定位置:

    >>> pyautogui.moveTo(100,200)
    
  • 触发鼠标点击:

    >>> pyautogui.click()
    

更多细节:PyAutoGUI

只需尝试这段代码:

#!/usr/bin/python

import objc

class ETMouse():    
    def setMousePosition(self, x, y):
        bndl = objc.loadBundle( CoreGraphics , globals(), 
                 /System/Library/Frameworks/ApplicationServices.framework )
        objc.loadBundleFunctions(bndl, globals(), 
                [( CGWarpMouseCursorPosition ,  v{CGPoint=ff} )])
        CGWarpMouseCursorPosition((x, y))

if __name__ == "__main__":
    et = ETMouse()
    et.setMousePosition(200, 200)

它在OSX豹10.5.6中运作。

当我想执行它时,我安装了Jython并使用了java.awt.Robot类。如果您需要制作CPython脚本,这显然是不适合的,但当您具有选择任何东西的灵活性时,它是一个不错的跨平台解决方案。

import java.awt

robot = java.awt.Robot()

robot.mouseMove(x, y)
robot.mousePress(java.awt.event.InputEvent.BUTTON1_MASK)
robot.mouseRelease(java.awt.event.InputEvent.BUTTON1_MASK)

你最好使用 AutoPy 软件包。它非常容易使用,而且跨平台。

把光标移动到(200,200)的位置:

import autopy
autopy.mouse.move(200,200)

来自geekorgy.com的Python脚本非常棒,但是由于我安装了更新版本的Python,我遇到了一些问题。因此,这里给其他寻找解决方案的人一些提示。

如果你在Mac OS 10.6上安装了Python 2.7,你有几种选择来让python从Quartz.CoreGraphics导入:

在终端中,在脚本路径之前,不要仅仅使用python,而是要使用python2.6

B) 您可以通过以下方式安装PyObjC

  1. Install easy_install from http://pypi.python.org/pypi/setuptools
  2. In the terminal, type which python and copy the path up through 2.7
  3. 然后输入 easy_install –-prefix /Path/To/Python/Version pyobjc==2.3

    例如:easy_install –-prefix /Library/Frameworks/Python.framework/Versions/2.7 pyobjc==2.3

  4. Inside the script type import objc at the top
  5. 如果easy_install第一次无法运行,您可能需要先安装核心包:

    例如: easy_install --prefix /Library/Frameworks/Python.framework/Versions/2.7 pyobjc-core==2.3

C)您可以将您的Python路径重置为原始的Mac OS Python:

  • In the terminal, type: defaults write com.apple.versioner.python Version 2.6

还有一个快速找出屏幕上 (x,y) 坐标的方法:

  1. Press Command+Shift+4 (screen grab selection)
  2. The cursor then shows the coordinates
  3. Then hit Esc to get out of it.

使用Quartz库中的CoreGraphics,例如:

from Quartz.CoreGraphics import CGEventCreate
from Quartz.CoreGraphics import CGEventGetLocation
ourEvent = CGEventCreate(None);
currentpos = CGEventGetLocation(ourEvent);
mousemove(currentpos.x,currentpos.y)

来源: Tony在Geekorgy页面的评论

这是使用Quartz库的完整示例:

#!/usr/bin/python
import sys
from AppKit import NSEvent
import Quartz

class Mouse():
    down = [Quartz.kCGEventLeftMouseDown, Quartz.kCGEventRightMouseDown, Quartz.kCGEventOtherMouseDown]
    up = [Quartz.kCGEventLeftMouseUp, Quartz.kCGEventRightMouseUp, Quartz.kCGEventOtherMouseUp]
    [LEFT, RIGHT, OTHER] = [0, 1, 2]

    def position(self):
        point = Quartz.CGEventGetLocation( Quartz.CGEventCreate(None) )
        return point.x, point.y

    def location(self):
        loc = NSEvent.mouseLocation()
        return loc.x, Quartz.CGDisplayPixelsHigh(0) - loc.y

    def move(self, x, y):
        moveEvent = Quartz.CGEventCreateMouseEvent(None, Quartz.kCGEventMouseMoved, (x, y), 0)
        Quartz.CGEventPost(Quartz.kCGHIDEventTap, moveEvent)

    def press(self, x, y, button=1):
        event = Quartz.CGEventCreateMouseEvent(None, Mouse.down[button], (x, y), button - 1)
        Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)

    def release(self, x, y, button=1):
        event = Quartz.CGEventCreateMouseEvent(None, Mouse.up[button], (x, y), button - 1)
        Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)

    def click(self, button=LEFT):
        x, y = self.position()
        self.press(x, y, button)
        self.release(x, y, button)

    def click_pos(self, x, y, button=LEFT):
        self.move(x, y)
        self.click(button)

    def to_relative(self, x, y):
        curr_pos = Quartz.CGEventGetLocation( Quartz.CGEventCreate(None) )
        x += current_position.x;
        y += current_position.y;
        return [x, y]

    def move_rel(self, x, y):
        [x, y] = to_relative(x, y)
        moveEvent = Quartz.CGEventCreateMouseEvent(None, Quartz.kCGEventMouseMoved, Quartz.CGPointMake(x, y), 0)
        Quartz.CGEventPost(Quartz.kCGHIDEventTap, moveEvent)

上面的代码基于这些原始文件:Mouse.pymouseUtils.py

以下是使用上述类的演示代码:

# DEMO
if __name__ ==  __main__ :
    mouse = Mouse()
    if sys.platform == "darwin":
        print("Current mouse position: %d:%d" % mouse.position())
        print("Moving to 100:100...");
        mouse.move(100, 100)
        print("Clicking 200:200 position with using the right button...");
        mouse.click_pos(200, 200, mouse.RIGHT)
    elif sys.platform == "win32":
        print("Error: Platform not supported!")

您可以将两个代码块合并到一个文件中,赋予执行权限,并将其作为一个shell脚本运行。

最简单的方法?编译 这个 Cocoa 应用程序并传递它您的鼠标移动。

这是代码:

// File:
// click.m
//
// Compile with:
// gcc -o click click.m -framework ApplicationServices -framework Foundation
//
// Usage:
// ./click -x pixels -y pixels
// At the given coordinates it will click and release.

#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>

int main(int argc, char **argv) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSUserDefaults *args = [NSUserDefaults standardUserDefaults];


  // grabs command line arguments -x and -y
  //
  int x = [args integerForKey:@"x"];
  int y = [args integerForKey:@"y"];

  // The data structure CGPoint represents a point in a two-dimensional
  // coordinate system.  Here, X and Y distance from upper left, in pixels.
  //
  CGPoint pt;
  pt.x = x;
  pt.y = y;


  // https://stackoverflow.com/questions/1483567/cgpostmouseevent-replacement-on-snow-leopard
  CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, pt, kCGMouseButtonLeft);
  CGEventSetType(theEvent, kCGEventLeftMouseDown);
  CGEventPost(kCGHIDEventTap, theEvent);
  CFRelease(theEvent);

  [pool release];
  return 0;
}

被称为“click”的应用程序从CGRemoteOperation.h头文件中调用CGPostMouseEvent。它将坐标作为命令行参数,将鼠标移动到该位置,然后单击并释放鼠标按钮。

将上面的代码保存为click.m,在终端中打开,并切换到保存源代码的文件夹。然后通过键入gcc -o click click.m -framework ApplicationServices -framework Foundation来编译程序。不要被需要编译它所吓到,因为注释比代码多得多。这是一个非常简短的程序,只执行一个简单的任务。


另一种方法?导入pyobjc来访问一些OSX框架并通过这种方式访问鼠标。(参考第一个示例的代码,了解更多信息)。





相关问题
热门标签