Home > Blockchain >  Why do I need lambda func to have bind to <Key> call a method in Tkinter root window
Why do I need lambda func to have bind to <Key> call a method in Tkinter root window

Time:09-17

I have this code (sorry not really minimal):

import tkinter as tk

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        # tk.Frame.__init__(self, parent, *args, **kwargs)
        super().__init__(parent, *args, **kwargs)
        self.reader = parent
        
        # self.reader = tk.Toplevel(self)
        self.reader.title("XXX")
        self.reader.resizable(False, True)
        self.reader.geometry("650x5")
        self.reader.minsize(650,150)
        
        self.panel = tk.Text(self.reader, wrap="word", width=12, font=('Courier',14))
        self.viewer = tk.Text(self.reader, wrap="word", font=('Courier',14))
        
        self.viewer.insert(tk.INSERT,'h\nm\nbbb\ntt\n\nbbb')
        
        self.panel.insert(tk.INSERT,'hgggg\ngggm\nbbb\n\nbbbbtt\n\nbbb')
        
        self.labelv1 = tk.IntVar()
        # self.labelv1.set(int(self.panel.index('end-1c').split('.')[0]))
        
        self.labelv2 = tk.IntVar()
        # self.labelv2.set(int(self.viewer.index('end-1c').split('.')[0]))
        
        self.pippo = tk.StringVar()
        # self.pippo.set(("Panel : " str(self.labelv1) " Viewer : " str(self.labelv2)))
        
        self.label = tk.Label(self.reader, textvariable = self.pippo)
        self.label.pack(side='top')
        # self.update_labels()
        
        self.counter = tk.IntVar()
        self.counter.set(0)
                        
        # self.reader.bind_class('Text', '<Key>', self.update_labels())   #winfo_toplevel()
        # self.winfo_toplevel().bind("<Key>", self.update_labels())

        # self.reader.bind("<Key>", self.update_labels())
               
        self.reader.bind("<Key>",  lambda event: self.update_labels())
                
        self.scrollbar = tk.Scrollbar(self.reader, command=(self.on_scrollbar))
        
        self.scrollbar.pack(side="right", fill="y")
        self.panel.pack(side="left", fill="both", expand=True)
        self.viewer.pack(side="right", fill="both", expand=True)
                
        # Changing the settings to make the scrolling work
        # self.scrollbar['command'] = self.on_scrollbar
        self.panel['yscrollcommand'] = self.on_textscroll
        self.viewer['yscrollcommand'] = self.on_textscroll
        
    def update_labels(self, *args):

        print('OKK')

        self.labelv1.set(int(self.panel.index('end-1c').split('.')[0]))
        
        self.labelv2.set(int(self.viewer.index('end-1c').split('.')[0]))
        
        self.pippo.set("Panel : " str(self.labelv1.get()) " Viewer : " str(self.labelv2.get()))

        self.counter.set(self.counter.get()   1)
      
        print('updating labels : ' , self.counter.get(),'   /  ', self.pippo.get())
        return
                
    def on_scrollbar(self, *args):
        """
        Scrolls both text widgets when the scrollbar is moved
        """
        self.panel.yview(*args)
        self.viewer.yview(*args)
            
    def on_textscroll(self, *args):
        '''Moves the scrollbar and scrolls text widgets when the mousewheel
        is moved on a text widget'''
        self.scrollbar.set(*args)
        self.on_scrollbar('moveto', args[0])


if __name__ == "__main__":
    master = tk.Tk()
   
    MainApplication(master)  
    master.mainloop()  

I don't understand why does:

self.reader.bind("<Key>", lambda event: self.update_labels())

that binds any pressed key inside the text windows to a function update_labels() that reports the number of line text inside the window itself

works, while

self.reader.bind("<Key>", self.update_labels())

doesn't. I read a lot of docs and examples, here on SO too, but wasn't able to figure-out why the latter doesn't work as it should.

CodePudding user response:

The issue you have is because you are giving the output of the function and not the reference of it. To fix your issue you should do:

self.reader.bind("<Key>", self.update_labels)

and somewhere define:

def update_labels(self, event):
    ...
  • Related