首页 > 解决方案 > 为什么我需要 lambda func 才能绑定到在 Tkinter 根窗口中调用方法

问题描述

我有这个代码(抱歉不是最小的):

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()  

我不明白为什么会这样:

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

将文本窗口内的任何按下的键绑定到一个函数,该函数update_labels() 报告窗口本身内的行文本数

工作,而

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

没有。我在 SO 上也阅读了很多文档和示例,但无法弄清楚为什么后者不能正常工作。

标签: pythonpython-3.xtkintercallbackbinding

解决方案


您遇到的问题是因为您提供的是函数的输出而不是它的引用。要解决您的问题,您应该执行以下操作:

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

并在某处定义:

def update_labels(self, event):
    ...

推荐阅读