为tkinter小部件事件处理程序声明额外的参数

时间:2017-01-23 07:04:50

标签: python tkinter

关于如何为事件处理程序声明额外参数的New Mexico Tech website,提供了以下示例。

def __createWidgets(self):
    …
    self.cbList = []    # Create the checkbutton list
    for i in range(10):
        cb = tk.Checkbutton(self, …)
        self.cbList.append(cb)
        cb.grid( row=1, column=i)
        def handler(event, self=self, i=i):   ## 1
            return self.__cbHandler(event, i)
        cb.bind('<Button-1>', handler)
    …
def __cbHandler(self, event, cbNumber):
    …
  

备注## 1:这些行定义了一个期望的新函数处理程序   三个论点。第一个参数是传递给all的Event对象   事件处理程序,第二个和第三个参数将设置为   它们的默认值 - 我们需要传递它的额外参数。

问题:

  1. self=self中的def handler(...)争论是否需要通过 “自我”进入事件处理程序de __cbHandler(...)?默认情况下,“self”本身并不存在于事件处理程序中吗?
  2. 我写了一个测试代码来研究我的问题。用或 如果没有参数self=self,则测试代码的工作方式相同。是否存在事件处理方案,其中声明self=self参数是强制/必要的?
  3. 测试代码:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    
    try:
        import tkinter as tk # Python 3 tkinter modules
    except ImportError:
        import Tkinter as tk # Python 2 tkinter modules
    
    class NewListbox(tk.Frame):
        def __init__(self, parent, lb_values1, lb_values2):
            tk.Frame.__init__(self, parent)
            self.lb_values = tk.StringVar() 
            self.lb_values.set(lb_values1) 
            self.listbox = tk.Listbox(self, listvariable=self.lb_values)
            self.listbox.grid(row=2, column=0, sticky='nsew')
    
            # Having self=self and removing seems to make no difference.
            # self, appears to be pass on to the method def _update().
            def handler(event, self=self, values2=lb_values2): 
                return self._update(event, lb_values2)
            self.listbox.bind("<Button-1>", handler)
    
        def _update(self, event, newvalues):
            self.lb_values.set(newvalues)
    
    
    class App(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
            self.grid(row=0, column=0, sticky='nsew') 
            nlist1 = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
            nlist2 = ['Sarah', 'Jane', 'Oscar', 'Walley', 'Faith']
            self.lb = NewListbox(self, nlist1, nlist2)
            self.lb.grid(row=0, column=0, sticky='nsew')
    
    if __name__ == '__main__':
        root = tk.Tk()
        app = App(root)
        app.mainloop()
    

    原创方法(见下文):

    优点:易于实施。

    实施成本:增加小部件的属性数量。

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    
    try:
        import tkinter as tk # Python 3 tkinter modules
    except ImportError:
        import Tkinter as tk # Python 2 tkinter modules
    
    class NewListbox(tk.Frame):
        def __init__(self, parent, lb_values1, lb_values2):
            tk.Frame.__init__(self, parent)
            self.lb_values = tk.StringVar() 
            self.lb_values.set(lb_values1) 
            self.lb_values2 = lb_values2   # create new attribute to store lb_values2
            self.listbox = tk.Listbox(self, listvariable=self.lb_values)
            self.listbox.grid(row=2, column=0, sticky='nsew')
            self.listbox.bind("<Button-1>", self._update)
    
        def _update(self, event):
            self.lb_values.set(self.lb_values2) #load new attribute.
    
    
    class App(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
            self.grid(row=0, column=0, sticky='nsew') 
            nlist1 = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
            nlist2 = ['Sarah', 'Jane', 'Oscar', 'Walley', 'Faith']
            self.lb = NewListbox(self, nlist1, nlist2)
            self.lb.grid(row=0, column=0, sticky='nsew')
    
    if __name__ == '__main__':
        root = tk.Tk()
        app = App(root)
        app.mainloop()
    

0 个答案:

没有答案