How to make tkinter frames in a loop and update object values?

In this tutorial, we will explore the dynamic creation of Tkinter frames in a loop and the real-time update of object values within these frames. We'll walk through a practical example ? building a dynamic task manager that allows users to manage a list of tasks with toggling statuses.

Setting up Tkinter and Task Class

Tkinter comes pre-installed with Python, so no separate installation is needed. Let's define a simple Task class representing a task with a name and a status ?

import tkinter as tk

class Task:
    def __init__(self, name, status):
        self.name = name
        self.status = status

# Create sample tasks
task1 = Task("Write report", "Incomplete")
task2 = Task("Review code", "Incomplete") 
task3 = Task("Team meeting", "Complete")

print(f"{task1.name}: {task1.status}")
print(f"{task2.name}: {task2.status}")
print(f"{task3.name}: {task3.status}")
Write report: Incomplete
Review code: Incomplete
Team meeting: Complete

Creating Frames Dynamically in a Loop

The key concept is creating Tkinter frames within a loop while maintaining references to update object values. Here's how to create frames dynamically ?

import tkinter as tk

class Task:
    def __init__(self, name, status):
        self.name = name
        self.status = status

# Sample list of tasks
tasks = [
    Task("Write report", "Incomplete"),
    Task("Review code", "Incomplete"),
    Task("Team meeting", "Complete"),
]

def update_status(task, label):
    """Toggle task status and update the label"""
    if task.status == "Incomplete":
        task.status = "Complete"
    else:
        task.status = "Incomplete"
    label.config(text=f"Status: {task.status}")

def create_task_manager():
    root = tk.Tk()
    root.title("Dynamic Task Manager")
    root.geometry("400x300")

    # Create frames dynamically for each task
    for i, task in enumerate(tasks):
        # Create frame for each task
        frame = tk.Frame(root, relief="raised", borderwidth=2, padx=10, pady=5)
        frame.pack(fill=tk.X, padx=10, pady=5)

        # Task name label
        name_label = tk.Label(frame, text=f"Task: {task.name}", font=("Arial", 10, "bold"))
        name_label.pack(anchor=tk.W)

        # Status label (this will be updated)
        status_label = tk.Label(frame, text=f"Status: {task.status}")
        status_label.pack(anchor=tk.W)

        # Toggle button with lambda to capture current task and label
        toggle_btn = tk.Button(
            frame, 
            text="Toggle Status",
            command=lambda t=task, lbl=status_label: update_status(t, lbl)
        )
        toggle_btn.pack(anchor=tk.E, pady=2)

    root.mainloop()

if __name__ == "__main__":
    create_task_manager()

Key Points for Dynamic Frame Creation

When creating frames in loops and updating object values, consider these important points ?

  • Lambda Closure: Use lambda t=task, lbl=status_label to capture the current loop variables

  • Object References: Maintain references to both the task object and the UI label for updates

  • Frame Organization: Use pack() with proper anchoring for clean layout

  • State Management: Update both the object's state and the UI display simultaneously

Alternative Approach Using Class-Based Structure

For better organization, you can encapsulate the functionality in a class ?

import tkinter as tk

class Task:
    def __init__(self, name, status="Incomplete"):
        self.name = name
        self.status = status

class TaskManager:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Task Manager")
        self.root.geometry("450x350")
        
        self.tasks = [
            Task("Write documentation"),
            Task("Fix bugs"),
            Task("Deploy application", "Complete")
        ]
        
        self.create_gui()
    
    def toggle_status(self, task, status_label):
        """Toggle task status and update display"""
        task.status = "Complete" if task.status == "Incomplete" else "Incomplete"
        status_label.config(text=f"Status: {task.status}")
    
    def create_gui(self):
        """Create the main GUI with dynamic frames"""
        title_label = tk.Label(self.root, text="Task Manager", font=("Arial", 14, "bold"))
        title_label.pack(pady=10)
        
        # Create frames for each task
        for task in self.tasks:
            self.create_task_frame(task)
    
    def create_task_frame(self, task):
        """Create a frame for a single task"""
        frame = tk.Frame(self.root, relief="groove", borderwidth=2)
        frame.pack(fill=tk.X, padx=15, pady=5)
        
        # Task details
        name_lbl = tk.Label(frame, text=f"? {task.name}", font=("Arial", 10, "bold"))
        name_lbl.pack(anchor=tk.W, padx=5, pady=2)
        
        status_lbl = tk.Label(frame, text=f"Status: {task.status}")
        status_lbl.pack(anchor=tk.W, padx=5)
        
        # Toggle button
        btn = tk.Button(
            frame, 
            text="Toggle Status",
            bg="#4CAF50" if task.status == "Complete" else "#f44336",
            fg="white",
            command=lambda: self.toggle_status(task, status_lbl)
        )
        btn.pack(anchor=tk.E, padx=5, pady=5)
    
    def run(self):
        """Start the application"""
        self.root.mainloop()

# Run the application
if __name__ == "__main__":
    app = TaskManager()
    app.run()

Common Pitfalls and Solutions

Problem Cause Solution
Button always updates last item Lambda closure issue Use default parameters: lambda t=task
Labels don't update Lost reference to label Pass label as parameter to update function
Memory leaks Circular references Use weak references or proper cleanup

Conclusion

Creating dynamic Tkinter frames in loops requires careful handling of closures and object references. Use lambda with default parameters to capture loop variables and maintain references to UI elements for updates. This approach enables building responsive interfaces that can modify object states in real-time.

Updated on: 2026-03-27T16:34:53+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements