'How to update widgets in Tkinter for each execution of my function?

I essentially have a reddit bot using PRAW integrated into my first go at using Tkinter. A minimal working version of my code is as follows:

from tkinter import *
import praw

# Praw bot
r = praw.Reddit(
    user_agent="user_agent",
    client_id="client_id",
    client_secret="client_secret",
    username="username",
    password="password",
)

root = Tk()
search_box = Entry(root)
search_box.grid(column=0, row=1, sticky=W)


# Function that takes place when the button is clicked
def bot():
    # Praw gathers info about the selected user
    username = Entry.get(search_box)
    comment_karma = r.redditor(username).comment_karma

    # Labels are created for the collected data
    ck = Label(
        root,
        text=comment_karma
    )

    # Labels are made visible to the user
    ck.grid(column=1, row=1)


search = Button(
    root,
    text="search",
    command=bot,
)
search.grid(column=0, row=1, sticky=E)

root.mainloop()

What it does is gather information about whatever reddit username was inputted and creates and adds Labels with the info into the window. However, if I than input another username and repeat the function, it stacks on top of the previous widget. How can I change this?



Solution 1:[1]

The details of the second username are stacked on top of the first because the first username details are not removed from the screen. Therefore, the labels overlap with each other.

To solve the problem, the previous username labels can be removed using .destroy() as shown below:

# Function that takes place when the button is clicked
def bot():
    global ck
    
    # Praw gathers info about the selected user
    username = search_box.get()
    comment_karma = r.redditor(username).comment_karma
    
    try:
        ck.destroy()
    except NameError:
        pass
        
    # Labels are created for the collected data
    ck = Label(
        root,
        text=comment_karma
    )

    # Labels are made visible to the user
    ck.grid(column=1, row=1)

(Notice that ck is a global variable and the try-except block is used to prevent an error when ck is created for the first time)

You can follow the same approach to manage the other labels as well.

But this approach is not memory-efficient as you are creating new labels for every username. A better approach would be to create the labels beforehand and just change their values for every username using:

<label-widget>.configure(text = <text>)

The memory-efficient approach is given in the below working code.


Working Code:

from tkinter import *
import praw

# Praw bot
r = praw.Reddit(
    user_agent="user_agent",
    client_id="client_id",
    client_secret="client_secret",
    username="username",
    password="password",
)

root = Tk()

search_box = Entry(root)
search_box.grid(column=0, row=1, sticky=W)

#Comment Karma
ck = Label(root)
ck.grid(column=1, row=1)

# Function that takes place when the button is clicked
def bot():
    # Praw gathers info about the selected user
    username = search_box.get()
    comment_karma = r.redditor(username).comment_karma
    
    #Changing the value of comment karma
    ck.configure(text = comment_karma)

search = Button(
    root,
    text="search",
    command=bot,
)
search.grid(column=0, row=1, sticky=E)

root.mainloop()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1