A practical Python project to build a modern desktop GUI app that converts multiple images into a single PDF file โ with batch processing, file ordering, and a clean UI.
Weโll build CANVAPDF LITE, a lightweight offline tool using:
Tkinter (GUI)
ttkbootstrap (modern UI styling)
Pillow (image processing)
threading + queue (smooth background processing)
๐ Pro Version / Source & Upgrade:
https://matetools.gumroad.com/l/canva-pdf-pro
๐ What You Will Build
By the end of this tutorial, youโll have:
A desktop GUI app for image-to-PDF conversion
Drag-free file management (add files/folders)
Manual ordering system (move up/down)
Background processing (no UI freezing)
Live progress tracking
About window + menu system
๐ง Project Architecture Overview
This app is structured into clear sections:
UI Layer (Tkinter + ttkbootstrap)
File Management System
Image Processing Engine (Pillow)
Thread Worker (background task)
Queue-based UI updater
๐ฆ Step 1: Install Dependencies
pip install pillow ttkbootstrap
โ๏ธ Step 2: Initialize the App
We start by setting up the main window using a modern theme:
app = tk.Tk()
style = tb.Style("superhero")
app.title("CANVAPDF LITE v1.1.0")
app.geometry("1100x680")
app.minsize(900, 650)
๐ ttkbootstrap gives Tkinter a modern UI instantly.
๐ Step 3: File Handling System
We store selected images globally:
selected_files = []
SUPPORTED_FORMATS = (".png", ".jpg", ".jpeg")
Add Files
files = filedialog.askopenfilenames(
filetypes=[("Images", "*.png *.jpg *.jpeg")]
)
Add Folder (Batch Import)
We scan directories using os.walk():
for root, _, files in os.walk(folder):
for name in files:
p = Path(root) / name
๐งพ Step 4: Display File List in UI
We update the listbox dynamically:
file_listbox.delete(0, "end")
for f in selected_files:
file_listbox.insert("end", os.path.basename(str(f)))
๐ผ Step 5: Move Files Up & Down
We allow manual ordering:
selected_files[i], selected_files[i - 1] = selected_files[i - 1], selected_files[i]
This is useful when ordering pages in the final PDF.
๐ผ๏ธ Step 6: Image to PDF Conversion Engine
Each image is opened and converted:
def open_image(path):
return Image.open(path).convert("RGB")
Then we combine everything:
images[0].save(
save_path,
save_all=True,
append_images=images[1:]
)
๐ This is the core of the PDF generator.
๐งต Step 7: Run Processing in Background Thread
To avoid UI freezing:
threading.Thread(target=worker, daemon=True).start()
Why this matters:
Tkinter runs on a single thread
Heavy tasks freeze UI unless threaded
๐ Step 8: Live Progress Updates (Queue System)
We safely update UI from worker thread:
ui_queue.put((cmd, data))
Then UI listens every 100ms:
app.after(100, process_queue)
โ Step 9: Stop Functionality
We allow canceling the process:
stop_event.set()
This helps users stop long conversions safely.
๐จ Step 10: Modern UI Features
Using ttkbootstrap we add:
Buttons with styles
Progress bars
Status indicators
Clean layout system
Example:
tb.Button(actions, text="๐ Generate PDF", bootstyle="success")
โน๏ธ Step 11: About Window
We added a full About dialog:
App info
Features list
Store link button
๐ Project Link (Pro Version)
๐ Upgrade / Download / Support:
https://matetools.gumroad.com/l/canva-pdf-pro
๐ฏ Final Result
You now have a fully working:
โ Desktop PDF generator
โ Batch image importer
โ Reorder system
โ Thread-safe GUI
โ Modern Tkinter UI
๐ง What You Learned
Tkinter GUI structure
File system integration
Pillow image processing
Multithreading in desktop apps
Queue-based UI updates
Modern Python desktop design patterns
Top comments (0)