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
相关产品推荐
相关产品推荐

