Mastering Tkinter: Build a Dynamic Search & Filter Data Grid in a Scrollable Frame

Scrolled frame with search data row

Managing large datasets in a desktop application requires more than just a scrollbar; it needs a functional way to find information quickly. In this tutorial, we demonstrate how to build a Dynamic Search & Filter System within a Tkinter Scrollable Frame. By leveraging the power of the Canvas widget and real-time event tracing, you can create a high-performance data grid that responds instantly to user input.

This implementation covers several essential GUI development concepts:

  • Real-time Filtering: Using StringVar tracing to filter records as the user types.
  • Dynamic Grid Management: Efficiently showing and hiding rows using grid() and grid_forget() to avoid UI clutter.
  • Canvas Architecture: Building a robust scrollable container that handles hundreds of widgets without layout breaking.
  • Data Set Integration: Populating the interface from a Python list of tuples, simulating a real-world database or CSV source.
  • Enhanced UX: Native mouse wheel support integrated directly into the scrollable area for smooth navigation.
import tkinter as tk
from tkinter import ttk

# 1. List of Data Sets (Student Records)
data = [
    (1, 'John Deo', 'Four', 75, 'female'), (2, 'Max Ruin', 'Three', 85, 'male'),
    (3, 'Arnold', 'Three', 55, 'male'), (4, 'Krish Star', 'Four', 60, 'female'),
    (5, 'John Mike', 'Four', 60, 'female'), (6, 'Alex John', 'Four', 55, 'male'),
    (7, 'My John Rob', 'Five', 78, 'male'), (8, 'Asruid', 'Five', 85, 'male'),
    (9, 'Tes Qry', 'Six', 78, 'male'), (10, 'Big John', 'Four', 55, 'female'),
    (11, 'Ronald', 'Six', 89, 'female'), (12, 'Recky', 'Six', 94, 'female'),
    (13, 'Kty', 'Seven', 88, 'female'), (14, 'Bigy', 'Seven', 88, 'female'),
    (15, 'Tade Row', 'Four', 88, 'male'), (16, 'Gimmy', 'Four', 88, 'male'),
    (17, 'Tumyu', 'Six', 54, 'male'), (18, 'Honny', 'Five', 75, 'male'),
    (19, 'Tinny', 'Nine', 18, 'male'), (20, 'Jackly', 'Nine', 65, 'female'),
    (21, 'Babby John', 'Four', 69, 'female'), (22, 'Reggid', 'Seven', 55, 'female'),
    (23, 'Herod', 'Eight', 79, 'male'), (24, 'Tiddy Now', 'Seven', 78, 'male'),
    (25, 'Giff Tow', 'Seven', 88, 'male'), (26, 'Crelea', 'Seven', 79, 'male'),
    (27, 'Big Nose', 'Three', 81, 'female'), (28, 'Rojj Base', 'Seven', 86, 'female'),
    (29, 'Tess Played', 'Seven', 55, 'male'), (30, 'Reppy Red', 'Six', 79, 'female'),
    (31, 'Marry Toeey', 'Four', 88, 'male'), (32, 'Binn Rott', 'Seven', 90, 'female'),
    (33, 'Kenn Rein', 'Six', 96, 'female'), (34, 'Gain Toe', 'Seven', 69, 'male'),
    (35, 'Rows Noump', 'Six', 88, 'female')
]

# Storage for filtering references
row_storage = []

def update_search(*args):
    search_term = search_var.get().lower()
    for item in row_storage:
        for w in item['widgets']:
            w.grid_forget()
            
    current_row_idx = 1 
    for item in row_storage:
        if search_term in item['name'].lower() or search_term in item['class'].lower():
            for col_idx, w in enumerate(item['widgets']):
                w.grid(row=current_row_idx, column=col_idx, padx=5, pady=2)
            current_row_idx += 1

def _on_mousewheel(event):
    canvas.yview_scroll(int(-1*(event.delta/120)), "units")

root = tk.Tk()
root.title("plus2net - Search & Filter Scrolled Frame")
root.geometry("600x500")

search_frame = tk.Frame(root, pady=10)
search_frame.pack(fill=tk.X)
tk.Label(search_frame, text=" Search (Name/Class): ", font=('Arial', 10, 'bold')).pack(side=tk.LEFT)

search_var = tk.StringVar()
search_var.trace_add("write", update_search)
tk.Entry(search_frame, textvariable=search_var, width=30).pack(side=tk.LEFT)

container = tk.Frame(root)
container.pack(fill=tk.BOTH, expand=True)

canvas = tk.Canvas(container)
scrollbar = ttk.Scrollbar(container, orient=tk.VERTICAL, command=canvas.yview)
scrollable_frame = tk.Frame(canvas)

scrollable_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)

canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.bind_all("<MouseWheel>", _on_mousewheel)

headers = ["ID", "Name", "Class", "Mark", "Gender"]
for col, text in enumerate(headers):
    tk.Label(scrollable_frame, text=text, font=('Arial', 10, 'bold'), width=12, relief="raised").grid(row=0, column=col)

for i, student in enumerate(data, start=1):
    widgets_in_row = []
    for col_idx, value in enumerate(student):
        lbl = tk.Label(scrollable_frame, text=value, width=12, relief="groove", bg="white")
        lbl.grid(row=i, column=col_idx, padx=5, pady=2)
        widgets_in_row.append(lbl)
    
    row_storage.append({
        'widgets': widgets_in_row,
        'name': str(student[1]),
        'class': str(student[2])
    })

root.mainloop()

Subhendu Mohapatra — author at plus2net
Subhendu Mohapatra

Author

🎥 Join me live on YouTube

Passionate about coding and teaching, I publish practical tutorials on PHP, Python, JavaScript, SQL, and web development. My goal is to make learning simple, engaging, and project‑oriented with real examples and source code.



Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
©2000-2025   plus2net.com   All rights reserved worldwide Privacy Policy Disclaimer