Search code examples
pythontkintereventstkinter-entry

Tkinter. clear entry widget when clicked or in focus


I found similar questions but this one in particular. I ve tried a few different ways but i can t make it work. Total noob with events! I don t understand how to refer to the widget i guess... The app simply connects to a database, and the for loop creates a label, an entry and a button for each column in the table which will allow to insert new lines in the database. I want to default the entry widget with a 0, but i would like the 0 to clear as soon as the user clicks or focuses on the widget.

def confirm_ad_table():
    global widget_list

    #Create connection
    conn = sqlite3.connect('home_finance_database - Copia')
    #Create cursor
    c = conn.cursor()

    def clear_zero(widget):
        if widget.get() == '0':
            widget.delete(0, END)
                      
    c.execute(f"PRAGMA table_info ({entry_ad_table.get()})")
    column_list = [column[1] for column in c.fetchall()]

    for widget in widget_list:
        widget.destroy()
    #In Chat GPT's words: "If you destroy the widget the list still contains them. You need to clear the list""
    widget_list = []

    for col in column_list:
        lab_widget = Label(tab2, text=col)
        entry_widget = Entry(tab2, width=35)
        btn_widget = Button(tab2, text="Submit")

        entry_widget.bind("<FocusIn>", lambda: clear_zero(entry_widget))
        entry_widget.bind("<Key>", lambda: clear_zero(entry_widget))    

        widget_list.append(lab_widget)
        widget_list.append(entry_widget)
        widget_list.append(btn_widget)
    


    for num, widget in enumerate(widget_list):
        if type(widget) == Label:
            widget.grid(row=num+2, column=0)
        elif type(widget) == Entry:
            widget.grid(row=num+1, column=1)
            widget.insert(0, "0")
        elif type(widget) == Button:
            widget.grid(row=num, column=2)


    #Commit changes
    conn.commit()
    #Close connection
    conn.close()

Solution

  • When you bind an event to a function, the function is automatically passed an object that represents the event. Within that event object you can get a reference to the widget via the widget attribute.

    So, the first step is to define your function to accept this event object and use the widget attribute to access the entry widget that got the event:

    def clear_zero(event):
        if event.widget.get() == '0':
            event.widget.delete(0, END)
    

    Next, define your binding by removing the lambda and referencing the function directly:

    entry_widget.bind("<FocusIn>", clear_zero)
    entry_widget.bind("<Key>", clear_zero)