📊 Unit-IV: Python GUI Programming with Tkinter

Lecture 4: Event Handling, Input Validation & Database Integration

1. Event Handling in Tkinter

Tkinter uses event handlers to respond to user interactions. Events can be button clicks, key presses, mouse movements, etc.

Binding Events to Widgets

import tkinter as tk def button_click(event=None): print("Button was clicked!") label.config(text="Button Clicked!") def on_key_press(event): print(f"Key pressed: {event.char}") root = tk.Tk() # Button with command binding button = tk.Button(root, text="Click Me", command=button_click) button.pack(pady=10) # Binding to a specific key root.bind('', button_click) # Press Enter to trigger # Binding to all key presses root.bind('', on_key_press) # Label to show event results label = tk.Label(root, text="") label.pack(pady=10) root.mainloop()
Note: The event parameter contains information about the event, such as:
  • widget: The widget that received the event
  • x, y: Mouse coordinates
  • char: The character code for keyboard events
  • keysym: The key symbol for keyboard events
2. Common Event Types

Tkinter supports various event types. Here are some commonly used ones:

# Mouse events widget.bind('', callback) # Left mouse button widget.bind('', callback) # Double click widget.bind('', callback) # Left button drag widget.bind('', callback) # Mouse enters widget widget.bind('', callback) # Mouse leaves widget # Keyboard events widget.bind('', callback) # Any key press widget.bind('', callback) # Enter/Return key widget.bind('', callback) # Ctrl+C # Window events root.protocol('WM_DELETE_WINDOW', on_close) # Window close # Focus events widget.bind('', callback) # Widget gets focus widget.bind('', callback) # Widget loses focus
Important: When binding events, remember to include the event parameter in your callback function, even if you don't use it. For example: def callback(event):
3. Validating User Input

Tkinter provides built-in validation for Entry widgets to ensure users enter valid data.

Using the validate and validatecommand Options

import tkinter as tk from tkinter import messagebox def validate_number(input): if input.isdigit() or input == '': # Allow empty string for backspace return True elif input == '.': return True else: return False def on_submit(): if entry.get(): messagebox.showinfo("Success", f"You entered: {entry.get()}") root = tk.Tk() # Register the validation function vcmd = (root.register(validate_number), '%P') # Create and pack widgets label = tk.Label(root, text="Enter a number:") label.pack(pady=5) entry = tk.Entry( root, validate='key', validatecommand=vcmd ) entry.pack(pady=5) submit_btn = tk.Button(root, text="Submit", command=on_submit) submit_btn.pack(pady=10) root.mainloop()

Input Validation Demo

Please enter a valid number

Common Validation Types

  • %d - Action code (0=delete, 1=insert, -1=other)
  • %i - Index of the insertion/deletion
  • %P - Value of the entry if the edit is allowed
  • %s - Value of the entry before the edit
  • %S - The text string being inserted or deleted
  • %v - The current value of the widget's validate option
  • %V - The validation condition that triggered the callback
  • %W - The widget's name
4. Integrating Tkinter with SQLite

SQLite is a lightweight database that comes built-in with Python, making it perfect for Tkinter applications.

Basic Database Operations

import tkinter as tk from tkinter import messagebox import sqlite3 from sqlite3 import Error def create_connection(): conn = None try: conn = sqlite3.connect('database.db') return conn except Error as e: print(e) return conn def create_table(conn): try: cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE NOT NULL, age INTEGER ) ''') conn.commit() except Error as e: print(e) def add_user(): name = name_entry.get() email = email_entry.get() age = age_entry.get() if not name or not email: messagebox.showerror("Error", "Name and email are required!") return try: conn = create_connection() cursor = conn.cursor() cursor.execute(''' INSERT INTO users (name, email, age) VALUES (?, ?, ?) ''', (name, email, age)) conn.commit() messagebox.showinfo("Success", "User added successfully!") clear_entries() display_users() except sqlite3.IntegrityError: messagebox.showerror("Error", "Email already exists!") except Error as e: messagebox.showerror("Error", str(e)) finally: if conn: conn.close() def display_users(): try: conn = create_connection() cursor = conn.cursor() cursor.execute("SELECT * FROM users") rows = cursor.fetchall() # Clear the listbox user_list.delete(0, tk.END) # Add column headers user_list.insert(tk.END, "ID\tName\tEmail\tAge") user_list.insert(tk.END, "-" * 40) # Add user data for row in rows: user_list.insert(tk.END, f"{row[0]}\t{row[1]}\t{row[2]}\t{row[3] if row[3] else 'N/A'}") except Error as e: messagebox.showerror("Error", str(e)) finally: if conn: conn.close() def clear_entries(): name_entry.delete(0, tk.END) email_entry.delete(0, tk.END) age_entry.delete(0, tk.END) # Create the main window root = tk.Tk() root.title("User Management System") root.geometry("600x400") # Create database and table if they don't exist conn = create_connection() if conn is not None: create_table(conn) conn.close() # Create and pack widgets tk.Label(root, text="Name:").pack(pady=5) name_entry = tk.Entry(root, width=40) name_entry.pack(pady=5) tk.Label(root, text="Email:").pack(pady=5) email_entry = tk.Entry(root, width=40) email_entry.pack(pady=5) tk.Label(root, text="Age:").pack(pady=5) age_entry = tk.Entry(root, width=10) age_entry.pack(pady=5) add_btn = tk.Button(root, text="Add User", command=add_user) add_btn.pack(pady=10) # Create a listbox to display users user_list = tk.Listbox(root, width=80, height=10) user_list.pack(pady=10) # Display existing users display_users() root.mainloop()
Database Operations in Tkinter:
  1. Connection: Always open and close database connections properly
  2. Error Handling: Use try-except blocks to handle database errors
  3. Transactions: Use commit() to save changes and rollback() on errors
  4. Security: Use parameterized queries to prevent SQL injection
5. CRUD Operations with Tkinter

Implementing Create, Read, Update, and Delete operations in a Tkinter application.

Example Database Table: Products

ID Name Price Stock Actions
1 Laptop $999.99 15
2 Smartphone $699.99 30

CRUD Operations Code Structure

# Create (Insert) def create_product(): # Get values from entries # Validate input # Insert into database # Refresh the view pass # Read (Select) def read_products(): # Query all products # Display in a listbox or treeview pass # Update def update_product(): # Get selected product ID # Get updated values # Update database # Refresh the view pass # Delete def delete_product(): # Get selected product ID # Confirm deletion # Delete from database # Refresh the view pass
Best Practices:
  • Always validate user input before database operations
  • Use transactions for multiple related operations
  • Provide feedback to users after each operation
  • Handle exceptions and display user-friendly error messages
  • Consider using the Model-View-Controller (MVC) pattern for larger applications
Summary

In this lecture, we've covered:

  • Event Handling: Binding events to widgets and handling user interactions
  • Input Validation: Ensuring data integrity with validation rules
  • Database Integration: Connecting Tkinter with SQLite
  • CRUD Operations: Implementing Create, Read, Update, and Delete functionality

Practice Exercise:

Create a Tkinter application for a simple library management system with the following features:

  1. A form to add new books with fields: Title, Author, ISBN, and Quantity
  2. Input validation for all fields
  3. A list to display all books in the library
  4. Functionality to update book details
  5. Functionality to delete books from the library
  6. Search functionality to find books by title or author

Use SQLite to store the library data and implement proper error handling throughout the application.