You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python获取触摸屏的多点触摸位置(无需Kivy)

全局多点触摸输入监听方案(无窗口)

下面分平台给出Python实现方案,和你用pynput监听鼠标的逻辑类似,能在无额外窗口的情况下捕获全屏幕的触摸位置:

Windows平台

Windows系统的触摸事件通过系统消息WM_TOUCH传递,我们可以用pywin32库创建一个隐藏的消息窗口来监听这些事件。

步骤1:安装依赖

pip install pywin32

代码实现

import win32api
import win32con
import win32gui
import win32ui

class TouchListener:
    def __init__(self):
        # 创建隐藏窗口用于接收消息
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = self.wnd_proc
        wc.lpszClassName = "TouchListenerWindow"
        wc.hInstance = win32api.GetModuleHandle(None)
        class_atom = win32gui.RegisterClass(wc)
        self.hwnd = win32gui.CreateWindow(
            class_atom, "TouchListener", 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None
        )
        # 注册触摸输入
        win32gui.RegisterTouchWindow(self.hwnd, win32con.TWF_FINETOUCH)

    def wnd_proc(self, hwnd, msg, wparam, lparam):
        if msg == win32con.WM_TOUCH:
            # 解析触摸事件
            touch_inputs = win32gui.GetTouchInputInfo(lparam)
            for ti in touch_inputs:
                # 获取触摸ID、坐标、状态
                touch_id = ti.dwID
                x = ti.x // 100  # Windows触摸坐标单位是0.01像素,转成整数像素
                y = ti.y // 100
                if ti.dwFlags & win32con.TOUCHEVENTF_DOWN:
                    print(f"触摸点 {touch_id} 按下,位置: ({x}, {y})")
                elif ti.dwFlags & win32con.TOUCHEVENTF_UP:
                    print(f"触摸点 {touch_id} 抬起,位置: ({x}, {y})")
                elif ti.dwFlags & win32con.TOUCHEVENTF_MOVE:
                    print(f"触摸点 {touch_id} 移动,位置: ({x}, {y})")
            win32gui.CloseTouchInputHandle(lparam)
            return 0
        return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)

    def start(self):
        win32gui.PumpMessages()

if __name__ == "__main__":
    listener = TouchListener()
    listener.start()

Linux平台

Linux下可以通过libinput库直接读取触摸设备的输入事件,或者解析/dev/input/event*设备文件。这里推荐用python-libinput简化开发。

步骤1:安装依赖

pip install python-libinput
# 还需要系统依赖libinput-dev,以Debian/Ubuntu为例:
sudo apt-get install libinput-dev

代码实现

import libinput
import sys

def handle_event(event):
    if event.type == libinput.EventType.TOUCH_DOWN:
        touch = event.touch
        print(f"触摸点 {touch.id} 按下,位置: ({touch.x}, {touch.y})")
    elif event.type == libinput.EventType.TOUCH_UP:
        touch = event.touch
        print(f"触摸点 {touch.id} 抬起,位置: ({touch.x}, {touch.y})")
    elif event.type == libinput.EventType.TOUCH_MOTION:
        touch = event.touch
        print(f"触摸点 {touch.id} 移动,位置: ({touch.x}, {touch.y})")

if __name__ == "__main__":
    # 打开输入设备(需要root权限,或者将用户加入input组)
    try:
        udev = libinput.Udev()
        context = libinput.Context(udev)
        # 添加所有触摸设备
        devices = context.path_add_device(sys.argv[1]) if len(sys.argv) > 1 else context.udev_add_all()
        for dev in devices:
            print(f"监听设备: {dev.name}")
        # 循环处理事件
        while True:
            event = context.dispatch()
            if event:
                handle_event(event)
    except PermissionError:
        print("需要root权限,或者将当前用户加入input组:sudo usermod -aG input $USER")

注意:运行时需要指定触摸设备路径(比如/dev/input/event10),或者直接运行让程序自动识别,不过需要root权限或用户加入input组。

macOS平台

macOS可以通过Quartz框架的触摸事件API,用pyobjc绑定来实现全局监听。

步骤1:安装依赖

pip install pyobjc-framework-Quartz pyobjc-framework-Cocoa

代码实现

from Quartz import CGEventTapCreate, CGEventMaskBit, kCGEventTapOptionListenOnly, kCGHIDEventTap, CGEventTapEnable, CFRunLoopAddSource, CFRunLoopGetCurrent, CFMachPortCreateRunLoopSource, CFRelease
from Cocoa import NSEvent, NSApp

class TouchListener:
    def __init__(self):
        # 创建事件监听tap
        tap = CGEventTapCreate(
            kCGHIDEventTap,
            kCGEventTapOptionListenOnly,
            0,
            CGEventMaskBit(NSEvent.NSEventTypeTouchDown) | 
            CGEventMaskBit(NSEvent.NSEventTypeTouchUp) | 
            CGEventMaskBit(NSEvent.NSEventTypeTouchMoved),
            self.handle_event,
            None
        )
        if not tap:
            print("无法创建事件监听")
            exit(1)
        # 添加到运行循环
        run_loop_source = CFMachPortCreateRunLoopSource(None, tap, 0)
        CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes)
        CGEventTapEnable(tap, True)
        CFRelease(run_loop_source)

    def handle_event(self, proxy, event_type, event, refcon):
        # 解析触摸事件
        touch_event = NSEvent.eventWithCGEvent_(event)
        if touch_event:
            touches = touch_event.touchesMatchingPhase_inView_(NSEvent.NSTouchPhaseAny, None)
            for touch in touches:
                touch_id = touch.identity()
                location = touch.locationInWindow_(None)
                x, y = location.x, location.y
                phase = touch.phase()
                if phase == NSEvent.NSTouchPhaseBegan:
                    print(f"触摸点 {touch_id} 按下,位置: ({x}, {y})")
                elif phase == NSEvent.NSTouchPhaseEnded:
                    print(f"触摸点 {touch_id} 抬起,位置: ({x}, {y})")
                elif phase == NSEvent.NSTouchPhaseMoved:
                    print(f"触摸点 {touch_id} 移动,位置: ({x}, {y})")
        return event

if __name__ == "__main__":
    listener = TouchListener()
    NSApp.run()

注意:macOS需要在系统偏好设置的“安全性与隐私”中给终端/IDE授权“输入监控”权限,否则无法捕获全局触摸事件。


内容的提问来源于stack exchange,提问作者affect

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:22:46