背景与功能
该程序为解决用户频繁手动截图、整理文件的低效问题而设计,尤其适合需要批量截取屏幕内容的工作场景(如竞品功能对比、视频关键帧存档)。用户通过预定义快捷键触发截图,程序自动捕获屏幕指定区域(如REGION
坐标范围)或全屏画面,并按时间戳命名文件保存至指定目录(如D:\WorkFiles\...
),全程无需操作文件管理器。
核心特性
Queue
)传递GUI事件,分离键盘监听与界面渲染逻辑,防止界面卡顿;技术实现
程序基于keyboard
库实现全局热键监听,结合PIL.ImageGrab
完成屏幕图像采集,利用Tkinter
的after
方法实现异步GUI更新。通过os
模块自动创建多级保存目录,确保文件存储可靠性。代码结构清晰,预留扩展接口,可轻松集成OCR识别、图片压缩等进阶功能。
适用场景
适用于产品调研、远程协作、教育培训等需快速存档屏幕信息的场景,显著提升操作效率。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import keyboard
from PIL import ImageGrab
import tkinter as tk
import time
import os
from queue import Queue
# ============== 配置区域 ==============
REGION = (425, 65, 1490, 914) # 截图坐标 (左x, 上y, 右x, 下y),微信截图、QQ截图取屏幕坐标,截全屏就等于None
# REGION = None # 截全屏
SAVE_PATH = r"D:\WorkFiles\产品中心\0 竞品调研\视频截图"
# HOTKEY = "num 0" # 截图快捷键,小键盘0
HOTKEY = "page down" # 向下翻页键作为截图快捷键
EXIT_KEY = "esc" # 退出程序键
TIP_DURATION = 1000 # 提示显示时间(毫秒)
# ========================================
class ScreenshotHelper:
def __init__(self):
self.counter = 1
self.queue = Queue()
self.init_directory()
# 初始化Tkinter主线程
self.root = tk.Tk()
self.root.withdraw()
# 启动主循环定时器
self.root.after(100, self.process_gui_events)
print("截图工具已就绪")
print(f"快捷键:{HOTKEY.upper()} 截图")
print(f"退出键:{EXIT_KEY.upper()}")
def init_directory(self):
"""创建保存目录"""
if not os.path.exists(SAVE_PATH):
os.makedirs(SAVE_PATH)
def show_notification(self, message):
"""通过队列发送通知到主线程"""
self.queue.put(message)
def process_gui_events(self):
"""主线程定时处理GUI事件"""
try:
while not self.queue.empty():
message = self.queue.get_nowait()
self._create_notification_window(message)
finally:
# 持续轮询队列
self.root.after(100, self.process_gui_events)
def _create_notification_window(self, message):
"""创建固定尺寸提示窗口"""
tip = tk.Toplevel()
tip.attributes("-topmost", True)
tip.overrideredirect(True)
# 配置提示信息窗口尺寸
WINDOW_WIDTH = 300 # 可修改的宽度
WINDOW_HEIGHT = 30 # 可修改的高度
# 设置窗口不可调整大小
tip.resizable(False, False)
# 设置样式(背景色与标签一致)
tip.configure(
bg="#90EE90",
padx=5,
pady=2
)
# 创建标签(自动适应窗口尺寸)
label = tk.Label(tip,
text=message,
fg="white",
bg="#90EE90",
font=("微软雅黑", 9), # 根据高度调整字号
wraplength=WINDOW_WIDTH - 10) # 自动换行宽度
label.pack(fill=tk.BOTH, expand=True) # 填充整个窗口
# 固定窗口尺寸
tip.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}")
# 定位窗口到屏幕顶部居中
screen_width = self.root.winfo_screenwidth()
# screen_height = self.root.winfo_screenheight()
x = (screen_width - WINDOW_WIDTH) // 2
y = 20 # 距屏幕顶部20像素,可根据需要调整
tip.geometry(f"+{x}+{y}")
# 自动销毁
tip.after(TIP_DURATION, tip.destroy)
def capture(self):
"""截图操作"""
try:
filename = f"screen_{time.strftime('%Y%m%d_%H%M%S')}.png"
filepath = os.path.join(SAVE_PATH, filename)
# 截图并保存
img = ImageGrab.grab(bbox=REGION) if REGION else ImageGrab.grab()
img.save(filepath)
# 发送通知到GUI线程
self.show_notification(f"截图已保存:{filename}")
print(f"截图已保存:{os.path.join(SAVE_PATH, filename)}")
self.counter += 1
except Exception as e:
self.show_notification(f"截图失败:{str(e)}")
def exit_program(self):
"""安全退出程序"""
self.root.quit()
self.root.destroy()
print("正在退出程序...")
if __name__ == '__main__':
helper = ScreenshotHelper()
keyboard.add_hotkey(HOTKEY, helper.capture)
keyboard.add_hotkey(EXIT_KEY, helper.exit_program)
# 启动主循环
helper.root.mainloop()
print("程序已安全退出")