【问题标题】:How to pass arguments to lambda function in yscrollcommand in tkinter Listbox?如何在 tkinter Listbox 的 yscrollcommand 中将参数传递给 lambda 函数?
【发布时间】:2021-11-27 13:42:12
【问题描述】:

6 列表框对象在应用程序类的 for 循环中生成。 而它的yscrollcommand,6个函数都是硬编码的。 (0为def函数,1为def函数……)

如果我可以将索引参数传递给 lambda 函数, 列表滚动的6个函数可以压缩为1个for循环。

但是类中的函数,它有参数'self'。 这让我很困惑。

如何在 yscrollcommand 中将索引参数传递给 lambda 函数?

class app(tk.Frame):
    def __init__(self):
        self.root = tk.Tk()
        self.root.title('title something')

        # showing data frame
        self.data_frame = tk.LabelFrame(self.root, text='')
        self.data_frame.pack(fill='x')
        
        self.scrollbar = tk.Scrollbar(self.data_frame)
        self.scrollbar.pack(side='right', fill='y')
        
        self.listboxes = []
        self.listboxes_column = 6 # This can be vary.
        
        # listboxes are in a list.
        for i in range(self.listboxes_column):
            self.listboxes.append(tk.Listbox(self.data_frame, selectmode='extended', height=20, width=0, yscrollcommand = self.scrollbar.set))
            self.listboxes[i].pack(side='left')
            
        # when self.listboxes_column == 3
        # self.list_indexes == [[1, 2, 3], [0, 2, 3], [0, 1, 3], [0, 1, 2]]
        self.list_indexes = []
        for i in range(self.listboxes_column):
            indexes = [j for j in range(self.listboxes_column)]
            indexes.remove(i)
            self.list_indexes.append(indexes)

        # a listbox can scroll the others     
        # with lambda function and argument passing,
        # I want to make these 6 lines be in a for loop.
        # The from like this
        # for i in range(6):
        #     self.listboxes[index_argument].config(yscrollcommand = lambda ????? : self.list_scrolls_all(index_argument  ????? ))

        self.listboxes[0].config(yscrollcommand = self.list0_scrolls_all)
        self.listboxes[1].config(yscrollcommand = self.list1_scrolls_all)
        self.listboxes[2].config(yscrollcommand = self.list2_scrolls_all)
        self.listboxes[3].config(yscrollcommand = self.list3_scrolls_all)
        self.listboxes[4].config(yscrollcommand = self.list4_scrolls_all)
        self.listboxes[5].config(yscrollcommand = self.list4_scrolls_all)
        
        self.scrollbar.config(command=self.bar_scrolls_all)
        self.root.mainloop()


   # functions for lists scroll from 0 to 5.
   # I don't know how to pass argument via yscrollcommand in Listbox.
   # I want a form like this.
   #
   # def list_scrolls_all(self, index, *args):
   #     for i in self.list_indexes[index] :
   #         self.listboxes[i].yview_moveto(args[0])
   #     self.scrollbar.set(*args)

   def list0_scrolls_all(self, *args):
        for i in self.list_indexes[0] :
            self.listboxes[i].yview_moveto(args[0])
        self.scrollbar.set(*args)

    def list1_scrolls_all(self, *args):
        for i in self.list_indexes[1] :
            self.listboxes[i].yview_moveto(args[0])
        self.scrollbar.set(*args)


   # scroll bar
   def bar_scrolls_all(self,*args):
        for i in range(self.listboxes_column):
            self.listboxes[i].yview(*args)

【问题讨论】:

  • 这应该正确使用lambda来正确绑定函数:for i in range(6): self.listboxes[i].config(yscrollcommand=lambda index_argument=i: self.list_scrolls_all(index_argument))。方法中的self 参数(类中的函数称为方法)只是让方法使用类的变量。例如,当您在方法中使用 self.listboxes 时,self. 方法中的 self 参数。
  • 谢谢。我想我可以通过 yscrollcommand 将 int 和 *args 传递给函数。但似乎 yscrollcommand 只能传递 *args。

标签: python-3.x tkinter lambda arguments command


【解决方案1】:

我正好在做一个多列表框程序,所以我对你的代码做了一些修改。

我已经包含了flexx 函数,因此所有对象都完全灵活,尽管我不得不将pack 替换为grid

import tkinter as tk

def flexx(m, r = 0, c = 0, rw = 1, cw = 1):
    if r !=  None:
        m.rowconfigure(r, weight = rw)
    if c !=  None:
        m.columnconfigure(c, weight = cw)

class app:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title('title something')
        # make root flexible
        flexx(self.root)

        # showing data frame
        self.data_frame = tk.LabelFrame(self.root, text='Multiple Linked Listboxes')
        self.data_frame.grid(row = 0, column = 0, sticky = tk.NSEW)

        self.listboxes = []
        self.listboxes_column = 6 # This can be vary.

        self.scrollbar = tk.Scrollbar(self.data_frame)
        self.scrollbar.grid(row = 0, column = self.listboxes_column, sticky = tk.NS)

        # listboxes are in a list.
        for i in range(self.listboxes_column):
            self.listboxes.append(tk.Listbox(
                self.data_frame, selectmode='extended',
                height=20, width=0))
            self.listboxes[i].grid(row = 0, column = i, sticky = tk.NSEW)

            # make data_frame flexible
            flexx(self.data_frame, c = i)

            # populate listbox with some data for testing purposes
            for b in dir(self):
                self.listboxes[i].insert("end", b)

        # connect yscollcommand to all listboxes
        for a in self.listboxes:
            a["yscrollcommand"] = self.move_to

        if False: # Not sure waht this does
            # when self.listboxes_column == 3
            # self.list_indexes == [[1, 2, 3], [0, 2, 3], [0, 1, 3], [0, 1, 2]]
            self.list_indexes = []
            for i in range(self.listboxes_column):
                indexes = [j for j in range(self.listboxes_column)]
                indexes.remove(i)
                self.list_indexes.append(indexes)

        # connect scrollbar command to all y_views
        self.scrollbar.config(command = self.y_view)

    def y_view(self, *args):
        for a in self.listboxes:
            a.yview(*args)

    def move_to(self, *args):
        self.scrollbar.set(*args)
        self.y_view("moveto", args[0])

if __name__ == "__main__":
    demo = app()
    demo.root.mainloop()

【讨论】:

  • 哦,您的代码完全符合我的要求。
  • 好一个@4001jh,编码愉快。
猜你喜欢
  • 2016-04-10
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-25
相关资源
最近更新 更多