In this tutorial, we’ll create Lightshot Pro v2.8.0, a professional screenshot capture and annotation tool using Python. We’ll cover capturing screens, editing screenshots, tray integration, and hotkeys – all in a beginner-friendly, step-by-step format.
🛠 Step 1: Set Up Your Environment
First, make sure you have Python 3.10+ installed. Then, install the required packages:
pip install ttkbootstrap pillow pystray keyboard plyer
What these packages do:
ttkbootstrap: Modern themed GUI for Python (Tkinter-based)
Pillow: Image capture and editing
pystray: System tray icon support
keyboard: Hotkey detection
plyer: Desktop notifications
📁 Step 2: Create the Screenshot Folder
We need a folder to save our screenshots. Python can do this automatically:
import os
SCREENSHOT_DIR = os.path.join(os.getcwd(), "screenshots")
os.makedirs(SCREENSHOT_DIR, exist_ok=True)
os.getcwd() returns the current working directory.
os.makedirs(..., exist_ok=True) creates the folder if it doesn’t exist.
🖥 Step 3: Capture Screenshots
We’ll use Pillow’s ImageGrab to capture a specific region. Let’s create a function that starts a capture overlay:
from PIL import ImageGrab
import tkinter as tk
def start_capture():
overlay = tk.Toplevel()
overlay.attributes("-fullscreen", True)
overlay.attributes("-alpha", 0.25)
overlay.configure(bg="black")
canvas = tk.Canvas(overlay, cursor="cross")
canvas.pack(fill="both", expand=True)
start_x = start_y = end_x = end_y = 0
def on_mouse_down(e):
nonlocal start_x, start_y
start_x, start_y = e.x, e.y
def on_mouse_up(e):
nonlocal end_x, end_y
end_x, end_y = e.x, e.y
overlay.destroy()
capture_area(start_x, start_y, end_x, end_y)
canvas.bind("<ButtonPress-1>", on_mouse_down)
canvas.bind("<ButtonRelease-1>", on_mouse_up)
def capture_area(x1, y1, x2, y2):
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
img.save(os.path.join(SCREENSHOT_DIR, "shot.png"))
Explanation:
Toplevel() creates a transparent overlay for selection.
We track mouse down/up to define the capture area.
ImageGrab.grab(bbox=(x1, y1, x2, y2)) captures that region.
✏️ Step 4: Add a Simple Editor
Once we capture a screenshot, we want to annotate it. Here's a simple editor with arrows, rectangles, and blur:
from PIL import ImageDraw, ImageFilter, ImageTk
def open_editor(img):
editor = tk.Toplevel()
canvas = tk.Canvas(editor, width=img.width, height=img.height)
canvas.pack()
tk_img = ImageTk.PhotoImage(img)
canvas.create_image(0, 0, anchor="nw", image=tk_img)
start = None
def on_mouse_down(e):
nonlocal start
start = (e.x, e.y)
def on_mouse_up(e):
nonlocal start
if start:
x1, y1 = start
x2, y2 = e.x, e.y
draw = ImageDraw.Draw(img)
draw.rectangle([x1, y1, x2, y2], outline="red", width=3)
start = None
canvas.bind("<ButtonPress-1>", on_mouse_down)
canvas.bind("<ButtonRelease-1>", on_mouse_up)
Explanation:
ImageDraw.Draw(img) lets you draw shapes on the screenshot.
We bind mouse events to draw rectangles interactively.
You can extend this to arrows or blur regions using ImageFilter.
🖥 Step 5: Add Hotkeys
We want to start a capture using PrintScreen:
import keyboard
keyboard.add_hotkey("print screen", start_capture)
keyboard.add_hotkey runs start_capture() whenever PrintScreen is pressed.
🖱 Step 6: Add a Tray Icon
Using pystray, we can add a tray icon for quick actions:
from pystray import Icon, MenuItem as item
from PIL import Image, ImageDraw
def setup_tray():
icon_img = Image.new("RGB", (64, 64), "black")
draw = ImageDraw.Draw(icon_img)
draw.rectangle((16,16,48,48), outline="white", width=3)
def on_capture(icon, item):
start_capture()
def on_exit(icon, item):
icon.stop()
tray_icon = Icon("Lightshot", icon_img, "Lightshot", menu=(
item("Capture Screenshot", on_capture),
item("Exit", on_exit)
))
tray_icon.run_detached()
Explanation:
Creates a small black tray icon.
Right-click menu lets users capture screenshots or exit the app.
🌗 Step 7: Add Theme Switching
You can toggle between light/dark mode using a simple variable:
current_theme = "dark"
def toggle_theme():
global current_theme
current_theme = "light" if current_theme == "dark" else "dark"
Integrate this with tray menu or buttons to switch overlay colors.
💾 Step 8: Combine Everything
Finally, create the main application window using ttkbootstrap:
import ttkbootstrap as tb
app = tb.Window(themename="darkly")
app.title("Lightshot Pro")
# Add main buttons
tb.Button(app, text="📸 Capture Now", bootstyle="success", command=start_capture).pack(pady=20)
tb.Button(app, text="⚙ Settings", bootstyle="secondary").pack(pady=5)
tb.Button(app, text="✖ Exit", bootstyle="danger", command=app.quit).pack(pady=5)
# Bind PrintScreen
keyboard.add_hotkey("print screen", start_capture)
# Start tray in background
import threading
threading.Thread(target=setup_tray, daemon=True).start()
app.mainloop()
Modern GUI with ttkbootstrap
Buttons to capture screenshots, open settings, or exit
Hotkeys and tray integration running in the background
🎉 Step 9: Next Steps
You now have a fully functional screenshot tool with:
Region selection
Annotations (rectangle, arrow, blur)
Hotkey support
Tray icon with menu
Light/Dark themes
You can expand it further with:
Undo/Redo functionality
Saving in multiple formats (PNG, JPG)
Advanced editor tools like arrows, text, or blur brushes
🔗 Get the Full Source Code
Clone the full project from GitHub:
https://github.com/rogers-cyber/LightshotPro
This tutorial breaks the project into small, understandable steps, perfect for beginners who want to build their own desktop apps in Python.

Top comments (0)