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

Python pynput Listener实现屏幕裁剪程序报错解决方法

屏幕裁剪工具报错修复方案

核心报错原因

你遇到的程序无响应/报错本质是GUI线程阻塞:pynput的鼠标监听器Listener.join()是阻塞式方法,直接在tkinter的主线程事件回调中运行会彻底卡住tkinter的主消息循环,触发系统级的程序无响应报错。

原有代码的其他问题

  • 快捷键触发后主窗口不会自动隐藏,会遮挡需要裁剪的屏幕区域
  • 裁剪坐标没有做大小校验,如果第二次点击的位置在第一次点击位置的左/上方,会传入非法参数导致裁剪失败
  • 冗余导入了未使用的keyboard库
  • 如果裁剪流程中途中断,D盘会残留未清理的临时截图文件
  • 鼠标监听直接跑在主线程,和tkinter的事件循环冲突

修复后完整可运行代码

import pyautogui
import tkinter as tk
from pynput.mouse import Listener
from PIL import Image
import os
import threading

def cropping(event=None):   
    coord = []
    temp_img_path = 'D:/myscreenshot.jpg'
    output_img_path = 'D:/cropped.jpg'
    # 最小化主窗口避免遮挡截图区域
    root.iconify()
    root.update()
    
    # 截取全屏
    full_screenshot = pyautogui.screenshot()
    full_screenshot.save(temp_img_path)
    im = Image.open(temp_img_path)

    # 鼠标点击回调
    def on_click(x,y,button,pressed):
        if pressed:
            coord.extend([int(x), int(y)])
            if len(coord) == 4:
                return False

    # 子线程运行鼠标监听,避免阻塞GUI主循环
    def run_listen():
        with Listener(on_click=on_click) as listener:
            listener.join()
        # 坐标兼容处理,支持任意顺序点击两个对角点
        left = min(coord[0], coord[2])
        top = min(coord[1], coord[3])
        right = max(coord[0], coord[2])
        bottom = max(coord[1], coord[3])
        # 执行裁剪
        cropped_im = im.crop((left, top, right, bottom))
        # 清理临时文件
        if os.path.exists(temp_img_path):
            os.remove(temp_img_path)
        # 保存并展示结果
        cropped_im.save(output_img_path)
        cropped_im.show()
        # 恢复主窗口,打开D盘目录
        root.deiconify()
        os.startfile('D:/')

    threading.Thread(target=run_listen, daemon=True).start()

# 主界面初始化
root = tk.Tk()
root.title('BetterWork')
canvas1 = tk.Canvas(root, width=400, height=100)
canvas1.pack()

def toggle_crop_func():
    if onButton['text'] == 'OFF':
        onButton['text'] = 'ON'
        onButton['bg'] = 'blue'
        root.bind('<Shift-Z>', cropping)
    else:
        root.unbind('<Shift-Z>')
        onButton['text'] = 'OFF'
        onButton['bg'] = 'red'
        
onButton = tk.Button(text='OFF', command=toggle_crop_func, bg='red', fg='white', font=15, width=25)
canvas1.create_window(200, 50, window=onButton)

root.mainloop()

使用流程

  • 运行程序,点击红色OFF按钮,按钮切换为蓝色ON状态,快捷键功能激活
  • 按下Shift+Z组合键,程序主窗口自动最小化
  • 鼠标点击两次,选中需要裁剪的屏幕区域对角点(无需严格按左上→右下顺序点击)
  • 裁剪完成后自动弹出结果预览,同时打开D盘根目录,裁剪结果保存为D:/cropped.jpg

注意:如果运行时提示D盘写入权限不足,将代码中temp_img_path和output_img_path的路径修改为你有写入权限的目录即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:48:11