NITDA/NCAIR Logo

Unified Learning Archive

Python Receipt GUI Tutorial

"A legacy that will echo till eternity"

Built by Group 5 โ€ข Powered by Elona โ€ข Honoring NITDA/NCAIR ๐Ÿ‡ณ๐Ÿ‡ฌ

Build a Receipt GUI with Python

Transform your command-line tool into a professional graphical interface

Complete GUI Tutorial

What You'll Build

This tutorial will guide you through creating a professional GUI for your receipt analyzer that:

  • Replaces command-line inputs with intuitive buttons
  • Provides visual feedback at each step
  • Maintains all the functionality of your existing tools
  • Follows NITDA/NCAIR coding standards

What is a GUI?

"A GUI is like a beautiful window or app with buttons, text, and file pickers โ€” instead of using the command line (black screen)."

Command Line Version

1. Add receipt
2. Process
3. Exit

GUI Version



GUI Features Overview

Feature GUI Implementation
Upload Receipt Button to select a photo from your computer
Extract Text Click a button to run OCR (read the receipt)
Show Items Display found items & prices in the interface
Categorize Items Button to sort items into categories automatically
Save as CSV Automatic saving to expenses.csv
View Dashboard Button to open the chart window

Tools You'll Use

Tkinter

Python's built-in GUI toolkit that creates windows, buttons, and inputs.

pytesseract

Optical Character Recognition (OCR) to read text from receipt images.

Pandas

Powerful data manipulation library for handling the expense data.

Matplotlib

Visualization library that draws the interactive expense charts.

Step-by-Step Implementation

1 Create a New File

receipt_gui.py

Save this in the same folder as your other receipt files

2 Starter GUI Template

Here's the complete code for your GUI application:

import tkinter as tk
from tkinter import filedialog, messagebox
import os
import pytesseract
import cv2
import csv
from datetime import datetime
from dashboard import ExpenseDataLoader, ExpenseDashboard  # From your dashboard.py

# Set up OCR path
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

class ReceiptApp:
    def __init__(self, master):
        self.master = master
        master.title("๐Ÿงพ Receipt Analyzer - Group 5")
        master.geometry("400x300")

        self.label = tk.Label(master, text="Smart Receipt Analyzer", font=("Arial", 14))
        self.label.pack(pady=10)

        self.upload_button = tk.Button(master, text="๐Ÿ“ Upload Receipt", command=self.upload_image)
        self.upload_button.pack(pady=5)

        self.process_button = tk.Button(master, text="โš™ Process Receipt", command=self.process_receipt)
        self.process_button.pack(pady=5)

        self.dashboard_button = tk.Button(master, text="๐Ÿ“Š Show Dashboard", command=self.show_dashboard)
        self.dashboard_button.pack(pady=5)

        self.status_label = tk.Label(master, text="", fg="green")
        self.status_label.pack(pady=10)

        self.receipt_file = ""

    def upload_image(self):
        self.receipt_file = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
        if self.receipt_file:
            self.status_label.config(text=f"Selected: {os.path.basename(self.receipt_file)}")

    def process_receipt(self):
        if not self.receipt_file:
            messagebox.showwarning("No File", "Please upload a receipt image first.")
            return

        img = cv2.imread(self.receipt_file)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        text = pytesseract.image_to_string(gray)

        with open("expenses.csv", 'a', newline='') as file:
            writer = csv.writer(file)
            if os.stat("expenses.csv").st_size == 0:
                writer.writerow(['Receipt', 'Item', 'Price', 'Category', 'Date'])

            lines = [line.strip() for line in text.split('\n') if line.strip()]
            for line in lines:
                if any(word in line.lower() for word in ['total', 'change']):
                    continue
                parts = line.rsplit(' ', 1)
                if len(parts) == 2:
                    item, price = parts
                    try:
                        amount = float(price.replace("โ‚ฆ", "").replace(",", "").strip())
                        category = "Uncategorized"
                        now = datetime.now().strftime("%Y-%m-%d %H:%M")
                        writer.writerow([self.receipt_file, item.strip(), amount, category, now])
                    except:
                        continue

        messagebox.showinfo("Done", "Receipt processed and saved.")
        self.status_label.config(text="โœ… Receipt saved.")

    def show_dashboard(self):
        loader = ExpenseDataLoader()
        totals = loader.load_data()
        if totals:
            dashboard = ExpenseDashboard(totals)
            dashboard.show_bar_chart()
        else:
            messagebox.showinfo("No Data", "No data to display.")

if __name__ == "__main__":
    root = tk.Tk()
    app = ReceiptApp(root)
    root.mainloop()

3 File Structure

๐Ÿ“ project-folder/
โ”œโ”€โ”€ receipt_gui.py
โ”œโ”€โ”€ dashboard.py # (with classes)
โ”œโ”€โ”€ expenses.csv # (automatically created)
โ””โ”€โ”€ tesseract image

4 How It Works

1
Upload Receipt

Click the button to select an image from your computer

2
Process Receipt

The system reads the text and saves results to CSV

3
Show Dashboard

View your categorized expenses in a professional chart

NITDA/NCAIR Standards Implemented

Professional Interface

  • Clean, intuitive button layout
  • Clear status messages
  • User-friendly error handling

Modular Design

  • Reuses existing dashboard components
  • Separate methods for each functionality
  • Easy to extend with new features

Error Handling

  • Checks for file existence
  • Validates data before processing
  • Provides helpful error messages

Documentation

  • Clear method responsibilities
  • Follows Python naming conventions
  • Self-documenting structure

GUI Demo Preview

๐Ÿงพ Receipt Analyzer - Group 5

Smart Receipt Analyzer

Selected: receipt1.jpg

This is how your GUI will appear when running the application

Simple Explanations for Everyone

Two-line explanations so any Group 5 member can understand and explain confidently:

What is a GUI?

A graphical user interface lets you click buttons instead of typing commands. It's like using a smartphone app instead of texting commands.

Tkinter

Python's built-in tool for making windows and buttons. Think of it as Lego blocks for building app interfaces.

Upload Button

Opens your file explorer to select a receipt photo. Works just like attaching a file to an email.

Process Button

Takes the photo and reads the text automatically. Like a scanner that understands receipts.

pytesseract (OCR)

The "eyes" of our program that read text from images. Similar to how your phone scans QR codes.

CSV File

Where all your receipt data gets saved. Like an Excel spreadsheet that updates automatically.

Dashboard Button

Shows your spending patterns in charts. Like a report card for your expenses.

Status Label

Shows messages about what's happening. Like the "Sending..." notification when you text someone.

Remember:

Our program works in 3 simple steps: 1) Upload โ†’ 2) Process โ†’ 3) View Results. Each button does one job, just like different kitchen appliances.

๐Ÿงพ receipt_gui.py โ€“ Line-by-Line Explanation

For NITDA/NCAIR Facilitators, Directors, and Team Members

1 IMPORTS SECTION

Python Imports
import tkinter as tk
from tkinter import filedialog, messagebox
import os
import pytesseract
import cv2
import csv
from datetime import datetime
from dashboard import ExpenseDataLoader, ExpenseDashboard
Line Explanation
tkinter Python's "construction kit" for windows and buttons (like building with LEGO blocks)
filedialog The "file explorer" popup that lets users select receipt images
messagebox Displays notification popups (like a phone's alert system)
pytesseract The "text scanner" that reads words from images (like a digital magnifying glass)
cv2 (OpenCV) Image processor that enhances receipts for better scanning
csv Creates Excel-compatible spreadsheets of your receipt data
dashboard import Connects to your chart-display code (like adding a report dashboard)

2 class ReceiptApp: The Brain of Your GUI

This class builds the entire interface - like an architect designing a house room-by-room.

class ReceiptApp:
    def __init__(self, master):

Key Concept: __init__ is the "construction phase" where we build all buttons and labels when the app starts.

Window Setup

master.title("๐Ÿงพ Receipt Analyzer - Group 5")
master.geometry("400x300")

Title: Like naming your business

Geometry: Sets window size (400px wide ร— 300px tall) - about half a laptop screen

Main Label

self.label = tk.Label(text="Smart Receipt Analyzer", 
                    font=("Arial", 14))
self.label.pack(pady=10)

Creates: The bold title at the top

pady=10: Adds 10 pixels of cushion space below it

Core Buttons

self.upload_button = tk.Button(
    text="๐Ÿ“ Upload Receipt",
    command=self.upload_image
)

What it does:

  1. Displays the folder icon (๐Ÿ“)
  2. Calls upload_image() when clicked
  3. Works like an "Attach File" button in email
self.process_button = tk.Button(
    text="โš™ Process Receipt",
    command=self.process_receipt
)

How it works:

  • Gears icon (โš™) hints at "processing"
  • Triggers text scanning when clicked
  • Only works after uploading a file
self.dashboard_button = tk.Button(
    text="๐Ÿ“Š Show Dashboard",
    command=self.show_dashboard
)

Key Features:

  • Chart icon (๐Ÿ“Š) indicates visualization
  • Requires processed data to display
  • Opens a separate chart window

Key Functions Explained

A upload_image(self)

def upload_image(self):
    self.receipt_file = filedialog.askopenfilename(
        filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")]
    )
    if self.receipt_file:
        self.status_label.config(
            text=f"Selected: {os.path.basename(self.receipt_file)}"
        )

Real-world analogy: Like using your phone's gallery picker to select a photo, then seeing its name appear on screen.

B process_receipt(self)

if not self.receipt_file:
    messagebox.showwarning("No File", "Please upload first.")
    return

Safety check: Prevents errors if users click Process without uploading - like a car that won't start without fuel.

img = cv2.imread(self.receipt_file)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
text = pytesseract.image_to_string(gray)

1. imread()

Loads the image like opening a photo album

2. cvtColor()

Converts to black & white for better text detection

3. image_to_string()

Extracts text like scanning a document

CSV Saving Process

with open("expenses.csv", 'a') as file:
    writer = csv.writer(file)
    if os.stat("expenses.csv").st_size == 0:
        writer.writerow(['Receipt', 'Item', ...])

    # ... parsing logic ...

    writer.writerow([self.receipt_file, item, price, ...])

How it organizes data:

  • 'a' mode = Appends new receipts without erasing old data
  • Checks if file is empty to add headers (like column titles in Excel)
  • Each row contains: [Image path, Item name, Price, Category, Date]

โœ… Functional Summary

Component Role Analogy
__init__ Builds the GUI skeleton Like constructing a house's framework
upload_image() File selection handler A document scanner's "Load" button
process_receipt() OCR & data extraction Like an accountant reviewing receipts
show_dashboard() Data visualization Generates report charts

Export Options:

Q&A: GUI Development Questions

Common questions answered in simple terms:

1 Why do we use Tkinter instead of other GUI tools?

Answer: Tkinter comes pre-installed with Python, so it works immediately without extra installations. It's like using the built-in calculator on your phone instead of downloading a new app.

2 What does master.geometry("400x300") do?

Answer: This sets the window size to 400 pixels wide and 300 pixels tall. Think of it like setting the dimensions of a picture frame before putting in your photo.

3 Why do we convert images to grayscale before OCR?

Answer: Color variations can confuse text recognition. Grayscale simplifies the image to just light/dark areas, like reading text on a photocopy instead of a colorful magazine.

4 How does the program know which part is price vs item?

Answer: It splits each line at the last space - the right part is treated as price (โ‚ฆ1,200) and everything left is the item (e.g., "Rice 5kg"). This works like reading a supermarket receipt from right to left for prices.

5 What happens if I click "Process" without uploading?

Answer: The if not self.receipt_file check shows a warning popup - like your phone saying "Please select a photo first" when you try to edit without choosing one.

6 Why use CSV instead of a database?

Answer: CSV files are simpler for beginners and open in Excel. It's like using a notebook instead of a filing cabinet when you're just starting to organize receipts.

7 What does root.mainloop() do?

Answer: This keeps the window open and responsive to your clicks, like how your phone screen stays on waiting for your touch. Without it, the window would open and immediately close.

Troubleshooting Tips:

๐Ÿง  Knowledge Mastery Quiz

Test your understanding of the Receipt Analyzer GUI