abrahavt
abrahavt

Reputation: 55

Tkinter - How to bind <Button-1> and call a function

I am trying to get the following code to work where event calls a function to clear an entry box. Can someone tell me what I am doing wrong. I am not too familiar with Tkinter.

import tkinter as tk
from tkinter import *

class Example(Frame):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.master.title("Create Trusted Facts")
        self.pack(fill=BOTH, expand=True)

        frame2 = Frame(self)
        frame2.pack(fill=X)

        reqSumLbl = Label(frame2, text="Request Summary", width=22)
        reqSumLbl.pack(side='left', padx=5, pady=5)

        reqSumBox = Entry(frame2, width=100, bg="White", fg="lightgrey", borderwidth=1)
        reqSumBox.insert(0, "Enter the Request Summary here")
        reqSumBox.pack(fill=X, padx=50, pady=5, expand=True)
        reqSumBox.bind("<Button-1>", self.clear_reqSumBox)

    def clear_reqSumBox(self, reqSumBox):
        reqSumBox.delete(0, END)
        reqSumBox.config(fg="black")
        global SummaryText
        SummaryText = reqSumBox.get()

def main():
    root = Tk()
    root.geometry("500x550+350+50")
    app = Example()

    root.mainloop()

if __name__ == '__main__':
        main()

Upvotes: 2

Views: 1709

Answers (3)

acw1668
acw1668

Reputation: 46678

The callback of bind() requires an argument which is the event object. So modify the callback function definition as below:

def clear_reqSumBox(self, event):
    # get the widget triggering this event
    reqSumBox = event.widget
    reqSumBox.delete(0, END)
    reqSumBox.config(fg="black")
    # after that reqSumBox.get() will return empty string
    global SummaryText
    # SummaryText = "" will have same result of below line
    SummaryText = reqSumBox.get()

However the entry will be cleared whenever you click on the entry. Is it really what you want?

Upvotes: 0

Tom Danilov
Tom Danilov

Reputation: 307

First of all, why do you have two imports at the start of your Python script at they're both the same library, choose one it's incorrect.

About your question, it fails because you didn't provide the clicked object, it provided you as the first argument of the bind function the Event that happened.

I recommend you make your object a part of your current working class (Class Example), like that:

import tkinter as tk
from tkinter import *

class Example(Frame):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.master.title("Create Trusted Facts")
        self.pack(fill=BOTH, expand=True)

        frame2 = Frame(self)
        frame2.pack(fill=X)

        reqSumLbl = Label(frame2, text="Request Summary", width=22)
        reqSumLbl.pack(side='left', padx=5, pady=5)

        # Check my changes here.
        self.reqSumBox = Entry(frame2, width=100, bg="White", fg="lightgrey", borderwidth=1)
        self.reqSumBox.insert(0, "Enter the Request Summary here")
        self.reqSumBox.pack(fill=X, padx=50, pady=5, expand=True)
        self.reqSumBox.bind("<Button-1>", self.clear_reqSumBox)

    # Changed the argument name to "event".
    def clear_reqSumBox(self, event):
        self.reqSumBox.delete(0, END)
        self.reqSumBox.config(fg="black")

def main():
    root = Tk()
    root.geometry("500x550+350+50")
    app = Example()

    root.mainloop()

if __name__ == '__main__':
    main()

Check where I comment and analyze this code.

Upvotes: 0

AashirOverflow
AashirOverflow

Reputation: 103

reqSumBox.bind("<Button-1>", self.clear_reqSumBox)

When binding any event to a function, it automatically needs to take in a parameter called event, there are 2 ways to fix your code.

1.

reqSumBox.bind("<Button-1>", lambda event: self.clear_reqSumBox)

Make lambda function which takes in event and calls function.

2.

def reqSumBox(self, reqSumBox, event=None)

Add optional event parameter in reqSumBox function.

I personally use the first one.

Upvotes: 1

Related Questions