目录
- 运行结果
- 全部代码
- 1. 工具介绍
- 2. 主要技术栈
- 3. 代码结构解析
- 3.1 主窗口的创建
- 3.2 创建 GUI 组件
- 3.3 截图逻辑
- 3.4 截图选择区域的实现
运行结果
全部代码
import tkinter as tk from tkinter import ttk import pyautogui import numpy as np from PIL import Image, ImageTk, ImageGrab import os from datetime import datetime import time class ImprovedScreenshotTool: def __init__(self): # Create the main window self.root = tk.Tk() self.root.title("精确截图工具") self.root.geometry("400x200") self.root.resizable(False, False) # Center the window self.center_window() # Create a frame for the controls control_frame = ttk.Frame(self.root) control_frame.pack(pady=10, fill=tk.X) # Create and place the screenshot button self.screenshot_btn = ttk.Button( control_frame, text="开始截图", width=20, command=self.prepare_screenshot ) self.screenshot_btn.pack(pady=10) # Status label self.status_label = ttk.Label(control_frame, text="就绪") self.status_label.pack(pady=5) # Preview frame self.preview_frame = ttk.LabelFrame(self.root, text="最近截图预览") self.preview_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True) self.preview_label = ttk.Label(self.preview_frame) self.preview_label.pack(fill=tk.BOTH, expand=True) # Variables for region selection self.start_x = 0 self.start_y = 0 self.end_x = 0 self.end_y = 0 # Save directory pictures_dir = os.path.join(os.path.expanduser("~"), "Pictures") if os.path.exists(pictures_dir): self.save_dir = pictures_dir else: self.save_dir = os.path.join(os.path.expanduser("~"), "Desktop") # Make sure the directory exists if not os.path.exists(self.save_dir): os.makedirs(self.save_dir) # Last saved file self.last_saved_file = None def center_window(self): # Get screen width and height screen_width = self.root.winfo_screenwidth() screen_height = self.root.winfo_screenheight() # Calculate position x = (screen_width - 400) // 2 y = (screen_height - 200) // 2 # Set window position self.root.geometry(f"400x200+{x}+{y}") def prepare_screenshot(self): # Update status self.status_label.config(text="准备截图...") self.root.update() # Force UI update # Minimize window self.root.withdraw() # Wait a moment for UI to update self.root.after(500, self.take_screenshot) def take_screenshot(self): # Create overlay window for selection overlay = ScreenshotOverlay(self) self.root.wait_window(overlay.overlay) # If cancelled, just return to normal if not hasattr(self, 'screenshot_region') or not self.screenshot_region: self.root.deiconify() self.status_llxOubxwjabel.config(text="已取消截图") return # Get the selection coordinates x1, y1, x2, y2 = self.screenshot_region # Convert to proper coordinates (top-left, bottom-right) left = min(x1, x2) top = min(y1, y2) right = max(x1, x2) bottom = max(y1, y2) # Ensure minimum size if right - left < 5 or bottom - top < 5: self.root.deiconify() self.status_label.config(text="选择区域太小") return # Take screenshot try: # Wait a moment to ensure overlay is gone time.sleep(0.3) # Capture the screen region screenshot = pyautogui.screenshot(region=(left, top, right-left, bottom-top)) # Generate filename timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = os.path.join(self.save_dir, f"screenshot_{timestamp}.png") # Save the screenshot screenshot.save(filename) self.last_saved_file = filename # Update preview self.update_preview(screenshot) # Update status self.status_label.config(text=f"截图已保存: {os.path.basename(filename)}") except Exception as e: self.status_label.config(text=f"截图错误: {str(e)}") # Show the main window again self.root.deiconify() def update_preview(self, image): # Resize for preview if needed preview_width = 360 preview_height = 100 width, height = image.size ratio = min(preview_width/width, preview_height/height) new_size = (int(width * ratio), int(height * ratio)) resized = image.resize(new_size, Image.LANCZOS) # Convert to PhotoImage photo = ImageTk.PhotoImage(resized) # Update label self.preview_label.config(image=photo) self.preview_label.image = photo # Keep a reference def run(self): self.root.mainloop() class ScreenshotOverlay: def __init__(self, parent): self.parent = parent # Create fullscreen overlay window self.overlay = tk.Toplevel() self.overlay.attributes('-fullscreen', True) self.overlay.attributes('-alpha', 0.3) self.overlay.attributes('-topmost', True) # Make it semi-transparent with dark background self.overlay.configure(bg='black') # Add a canvas for drawing self.canvas = tk.Canvas( self.overlay, bg='#1a1a1a', highlightthickness=编程0, cursor="crosshair" ) self.canvas.pack(fill=tk.BOTH, expand=True) # Variables for tracking self.start_x = None self.start_y = None self.rect_id = None self.magnifier_id = None self.coords_text_id = None # Instructions text self.canvas.create_text( self.overlay.winfo_screenwidth() // 2, 50, text="单击并拖动鼠标选择截图区域 | 按ESC取消", fill="white", font=("Arial", 16) ) # Bind events self.canvas.bind("<ButtonPress-1>", self.on_press) self.canvas.bind("<B1-Motion>", self.on_drag) self.canvas.bind("<ButtonRelease-1>", self.on_release) self.overlay.bind("<Escape>", self.on_cancel) # Take a full screenshot for the magnifier self.screen_image = pyautogui.screenshot() self.screen_array = np.array(self.screen_image) def on_press(self, event): # Record start position self.start_x = event.x self.start_y = event.y # Create rectangle self.rect_id = self.canvas.create_rectangle( self.start_x, self.start_y, self.start_x, self.start_y, outline="#00ff00", width=2, fill="" ) # Create magnifier circle self.magnifier_id = self.canvas.create_oval( event.x - 50, event.y - 50, event.x + 50, event.y + 50, outline="#ffffff", width=2, fill="#333333" ) # Create coordinate display self.coords_text_id = self.canvas.create_text( event.x, event.y - 60, text=f"({event.x}, {event.y})", fill="#ffffff", font=("Arial", 10) ) def on_drag(self, event): # Update rectangle self.canvas.coords( self.rect_id, self.start_x, self.start_y, event.x, event.y ) # Update magnifier position self.canvas.coords( self.magnifier_id, event.x - 50, event.y - 50, event.x + 50, event.y + 50 ) # Update coordinate display self.canvas.coords( self.coords_text_id, event.x, event.y - 60 ) self.canvas.itemconfig( self.coords_text_id, text=f"({event.x}, {event.y}) | 大小: {abs(event.x - self.start_x)}x{abs(event.y - self.start_y)}" ) # Draw selection area with fill (using a valid color format) self.canvas.itemconfig( self.rect_id, fill="#22ff22" # Changed to a valid semi-transparent green ) def on_release(self, event): # Store the selection coordinates in the parent self.parent.screenshot_region = ( self.start_x, self.start_y, event.x, event.y ) # Close the overlay self.overlay.destroy() def on_cancel(self, event): # Reset parent's screenshot region self.parent.screenshot_region = None # Close overlay self.overlay.destroy() if __name__ == "__main__": app = ImprovedScreenshotTool() app.run()
1. 工具介绍
该工具具有以下功能:
- 自定义截图区域:通过鼠标拖动选择截图区域。
- 自动保存截图:截图会自动保存到
Pictures
文件夹或桌面。 - 截图预览:最近一次截图会在工具界面中进行预览。
- 用户友好的操作提示:提供状态提示,让用户清楚当前操作。
2. 主要技术栈
本工具基于以下 python 库实现:
tkinter
:用于构建 GUI 界面。pyautogui
:用于屏幕截图。PIL (Pillow)
:用于图像处理和预览。numpy
:用于优化图像处理。datetime
&nbandroidsp;和os
:用于管理文件存储。
3. 代码结构解析
3.1 主窗口的创建
import tkinter as tk from tkinter import ttk import pyautogui import numpy as np from PIL import Image, ImageTk import os from datetime import datetime import time class ImprovedScreenshotTool: def __init__(self): self.root = tk.Tk() self.root.title("精确截图工具") self.root.geometry("400x200") self.root.resizable(False, False) self.center_window() self.create_widgets() self.setup_save_directory() def center_window(self): screen_width = self.root.winfo_screenwidth() screen_height = self.root.winfo_screenheight() x = (screen_width - 400) // 2 y = (screen_height - 200) // 2 self.root.geometry(f"400x200+{x}+{y}")
功能解析:
- 创建
Tk
窗口,设置标题、大小并居中。 center_window
方法用于获取屏幕尺寸并计算窗口居中位置。
3.2 创建 GUI 组件
def create_widgets(self): control_frame = ttk.Frame(self.root) control_frame.pack(pady=10, fill=tk.X) self.编程客栈screenshot_btn = ttk.Button(control_frame, text="开始截图", width=20, command=self.prepare_screenshot) self.screenshot_btn.pack(pady=10) self.status_label = ttk.Label(control_frame, text="就绪") self.status_label.pack(pady=5) self.preview_frame = ttk.LabelFrame(self.root, text="最近截图预览") self.preview_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True) self.preview_label = ttk.Label(self.preview_frame) self.preview_label.pack(fill=tk.BOTH, expand=True)
功能解析:
- 创建按钮
开始截图
,绑定prepare_screenshot
方法。 - 状态标签用于提示当前状态。
preview_frame
用于显示最近截图的预览。
3.3 截图逻辑
def prepare_screenshot(self): self.status_label.config(text="准备截图...") self.root.update() self.root.withdraw() self.root.after(500, self.take_screenshot)
功能解析:
- 按下截图按钮后,状态标签显示 “准备截图…”。
withdraw()
让主窗口最小化,避免干扰截图。after(500, self.take_screenshot)
让窗口延迟 0.5 秒后调用take_screenshot
。
def take_screenshot(self): overlay = ScreenshotOverlay(self) self.root.wait_window(overlay.overlay) if not hasattr(self, 'screenshot_region') or not self.screenshot_region: self.root.deiconify() self.status_label.config(text="已取消截图") return x1, y1, x2, y2 = self.screenshot_region left, top = min(x1, x2), min(y1, y2) right, bottom = max(x1, x2), max(y1, y2) if right - left < 5 or bottom - top < 5: self.root.deiconify() self.status_label.config(text="选择区域太小") return time.sleep(0.3) screenshot = pyautogui.screenshot(region=(left, top, right-left, bottom-top)) filename = os.path.join(self.save_dir, f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png") screenshot.save(filename) self.last_saved_file = filename self.update_preview(screenshot) self.status_label.config(text=f"截图已保存: {os.path.basename(filename)}") self.root.deiconify()
功能解析:
ScreenshotOverlay
负责创建全屏幕覆盖窗口,允许用户选择截图区域。- 获取选定区域的坐标,并检查区域大小是否有效。
pyautogui.screenshot(region=(left, top, width, height))
实现精准截图。- 保存截图并更新预览区域。
3.4 截图选择区域的实现
class ScreenshotOverlay: def __init__(self, parent): self.parent = parent self.overlay = tk.Toplevel() self.overlay.attributes('-fullscreen', True) self.overlay.attributes('-alpha', 0.3) self.overlay.attributes('-topmost', True) self.overlay.configure(bg='black') python self.canvas = tk.Canvas(self.overlay, bg='#1a1a1a', highlightthickness=0, cursor="crosshair") self.canvas.pack(fill=tk.BOTH, expand=True) self.canvas.bind("<ButtonPress-1>", self.on_press) self.canvas.bind("<B1-Motion>", self.on_drag) self.canvas.bind("<ButtonRelease-1>", self.on_release) self.overlay.bind("<Escape>", self.on_cancel)
功能解析:
- 创建全屏幕透明窗口,允许用户使用鼠标选择截图区域。
- 监听鼠标点击 (
on_press
)、拖动 (on_drag
)、释放 (on_release
) 事件。
以上就是使用Python结合Tkinter和PyAutoGUI开发精确截图工具的详细内容,更多关于Python Tkinter PyAutoGUI截图工具的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论