【问题标题】:Looping Buttons in tkinter and function assignmenttkinter 中的循环按钮和功能分配
【发布时间】:2017-03-22 21:23:35
【问题描述】:

我已经能够使用此代码在 tkinter 中生成按钮

for i in range(0, num_sheets):
            an_sheet = ttk.Button(self, text = "%s" % sh_names[i], command = partial(load_sheets))
            an_sheet.grid(row = 1, column = i+1, sticky='w', pady = 10, padx = 10)

现在这些按钮已根据 Excel 工作表中的工作表数生成,并且还分配了它们所代表的工作表的名称。但是,有一个功能可以打印所代表的每张纸的内容。

def load_sheets():
            for i,sheetname in enumerate(sh_names) :
                xl_sheet = wb.sheet_by_name(sh_names[i])
                print()
                print(sheetname)
                row = xl_sheet.row(0)   
                for idx, cell_obj in enumerate(row):
                    cell_type_str = ctype_text.get(cell_obj.ctype, 'unknown type')

                row = xl_sheet.nrows
                for col_idx in range(0, xl_sheet.ncols):
                    print ('Column: %s' % col_idx)
                    for row_idx in range(0, row):
                        cell_obj = xl_sheet.cell(row_idx, col_idx)
                        print ('Row: [%s] cell_obj: [%s]' % (row_idx, cell_obj))

现在的挑战是将函数绑定到按钮,以便在单击时打印出自己的内容。例如,当单击名为“sheet 1”的按钮时,应打印 sheet 1 的内容。

这是代码的完整结构。

class MainMenu(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)


        fname = join(dirname(dirname(abspath('C:/Users/qanda/OneDrive/Documents/Python Scripts/PEN'))), 'Python Scripts/PEN', 'Book1.xlsx')   
        wb = xlrd.open_workbook(fname)
        sh_names = wb.sheet_names()
        num_sheets = len(sh_names)

        def load_sheets():
            for i,sheetname in enumerate(sh_names) :
                xl_sheet = wb.sheet_by_name(sh_names[i])
                print()
                print(sheetname)
                row = xl_sheet.row(0)   
                for idx, cell_obj in enumerate(row):
                    cell_type_str = ctype_text.get(cell_obj.ctype, 'unknown type')

                row = xl_sheet.nrows
                for col_idx in range(0, xl_sheet.ncols):
                    print ('Column: %s' % col_idx)
                    for row_idx in range(0, row):
                        cell_obj = xl_sheet.cell(row_idx, col_idx)
                        print ('Row: [%s] cell_obj: [%s]' % (row_idx, cell_obj))


        for i in range(0, num_sheets):
            an_sheet = ttk.Button(self, text = "%s" % sh_names[i], command = partial(load_sheets))
            an_sheet.grid(row = 1, column = i+1, sticky='w', pady = 10, padx = 10)

【问题讨论】:

    标签: python excel tkinter


    【解决方案1】:

    定义一个函数来打印一张纸的内容,将纸的编号作为参数。然后,使用 functools.partial 将命令与每个按钮关联起来:

    def print_sheet(sheet_number):
        ...
    
    for i in range(0, num_sheets):
        an_sheet = ttk.Button(..., command = partial(print_sheet, i))
        ...
    

    下面是一个简短但完整的在循环中创建按钮的示例:

    import tkinter as tk
    from tkinter import ttk
    from functools import partial
    
    root = tk.Tk()
    
    def print_sheet(i):
        print("printing sheet %d" % i)
    
    for i in range(0, 5):
        button = ttk.Button(root, text="Button %d" % i,
                            command=partial(print_sheet, i))
        button.pack()
    
    root.mainloop()
    

    【讨论】:

    • 什么是functools.partial?听起来很有用
    • @JoshuaNixon:我以为你知道,因为你发布的代码正在使用它。至少,我假设当您在代码中使用partial 时,您使用的是functools.partial,即使您使用不正确。如果您不知道它的作用,请查一下。
    • @BryanOakley,我已经知道部分,但是,我尝试了您的建议,但没有奏效,它将最后一张表的文件位置分配给所有按钮。因此,当单击按钮时,打印出最后一张纸的文件位置。
    • @JoshuaNixon:partial 这个词确实在您的代码中:command = partial(load_sheets)。至于它不起作用,我可以向您保证,在我的回答中使用它时它会起作用。我已经更新了我的答案以包含一个完整的示例,以便您了解它是如何工作的。
    • 很好,我刚试了一下,效果很好。谢谢@BryanOakley
    【解决方案2】:

    所以你问的是如何遍历一组函数并分配它们?

    你可以用字典

    我的 A-level 计算课程示例

    self.screen_info = {"Email Customer":  {"button_names": ["Enter Email"],         "commands": [self.email_from_email]},
                        "Text Customer":   {"button_names": ["Enter Number"],        "commands": [self.text_from_number]},
                        "Backup Database": {"button_names": ["Choose Location"],     "commands": [backup_database.backup]},
                        "Export Database": {"button_names": ["As .txt", "As .csv"],  "commands": [lambda: export.main("txt"), lambda: export.main("csv")]}}
    
    
    def populate(self):
        for key in self.screen_info.keys():
    
            self.screen_info[key]["parent"] = tk.Frame(self.screens, width = 300, height = 300, bg = "#E6E6FA")
            self.screen_info[key]["parent"].place(relx = 0.5, rely = 0.5, anchor = tk.CENTER)
    
            for num in range(len(self.screen_info[key]["button_names"])):
                self.screen_info[key]["button_names"][num] = tk.Button(self.screen_info[key]["parent"],
                                                                       width = 20,
                                                                       text = self.screen_info[key]["button_names"][num],
                                                                       font = ("Ariel", 11, "bold"),
                                                                       command = self.screen_info[key]["commands"][num])
                self.screen_info[key]["button_names"][num].place(relx = 0.5, y = 60 + num * 40, anchor = tk.CENTER)
    

    所以这将遍历创建所有内容并分配命令的字典。我将 lambda 用于“导出数据库”,因为该函数需要一个参数,如果我不使用 lambda,那么该函数将在程序启动后立即运行

    编辑我用相关的小部件覆盖字典中的每个键值,但如果你不再引用它们,你甚至不需要设置变量,键给它们

    【讨论】:

      猜你喜欢
      • 2018-05-16
      • 2019-05-07
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      相关资源
      最近更新 更多