首页 > 解决方案 > 如何使用循环创建 Tkinter 小部件并为每个小部件分配自定义功能?

问题描述

这是我的第一个 python 应用程序,我知道它的许多缺陷,所以我会尝试从我的错误中学习。

我想了解如何通过将 tkinter 小部件的声明放在一个循环中来稍微缩短我的代码。

这是代码的一部分(有很多类似的部分,但我只会应用相同的逻辑):

varplies = StringVar(root)
varnotch = StringVar(root)
varspreader = StringVar(root)
varorder1 = StringVar(root)
varorder2 = StringVar(root)
def pliesto_uppercase(*args):
    varplies.set(varplies.get().upper())

def notchto_uppercase(*args):
    varnotch.set(varnotch.get().upper())

def spreaderto_uppercase(*args):
    varspreader.set(varspreader.get().upper())

def order1to_uppercase(*args):
    varorder1.set(varorder1.get().upper())

def order2to_uppercase(*args):
    varorder2.set(varorder2.get().upper())

varplies.trace_add('write', pliesto_uppercase)
varnotch.trace_add('write', notchto_uppercase)
varspreader.trace_add('write', spreaderto_uppercase)
varorder1.trace_add('write', order1to_uppercase)
varorder2.trace_add('write', order2to_uppercase)
self.rnplies_entry = Entry(self.entry_frame, background=rgbcon2((158, 174, 179)),
                           justify='center', textvariable=varplies, width=4)
self.rnnotch_entry = Entry(self.entry_frame, background=rgbcon2((158, 174, 179)),
                           justify='center', textvariable=varnotch, width=4)
self.rnspreader_entry = Entry(self.entry_frame, background=rgbcon2((158, 174, 179)),
                              justify='center', textvariable=varspreader, width=4)
self.rnorder1_entry = Entry(self.entry2_frame, background=rgbcon2((158, 174, 179)),
                            justify='center', textvariable=varorder1, width=8)
self.rnorder2_entry = Entry(self.entry2_frame, background=rgbcon2((158, 174, 179)),
                            justify='center', textvariable=varorder2, width=8)
self.rnplies_entry.grid(column=1, row=5, padx=5, sticky="SEW")
self.rnnotch_entry.grid(column=2, row=5, padx=5, sticky="SEW")
self.rnspreader_entry.grid(column=5, row=5, padx=5, sticky="SEW")
self.rnorder1_entry.grid(column=0, row=9, padx=5, pady=5, sticky="SEW")
self.rnorder2_entry.grid(column=0, row=10, padx=5, pady=5, sticky="SEW")



pfdate = StringVar(root)
pfdate.set('All')
pfmarker = StringVar(root)
pfmarker.set('All')
pfdate.trace('w', partial(changeplan, widget=pfdate))
pfmarker.trace('w', partial(changeplan, widget=pfmarker))
def planfilters():
    pdatelist = plandatefilter()
    pmarkerlist = planmarkerfilter()
    self.drop_datepl = OptionMenu(self.optionplan_frame, pfdate, *pdatelist)
    self.drop_datepl.config(bg=rgbcon2((39, 46, 46)), width=10, fg='white')
    self.drop_datepl.grid(row=5, column=0, sticky="E", padx=5, pady=5)
    self.drop_rnpl = OptionMenu(self.optionplan_frame, pfmarker, *pmarkerlist)
    self.drop_rnpl.config(bg=rgbcon2((39, 46, 46)), width=22, fg='white')
    self.drop_rnpl.grid(row=5, column=1, sticky="E", padx=5, pady=5)

简而言之,我想了解如何将其放入循环中,例如:

pl_filters = ('pfdate', 'pfmarker')
for opt_item in pl_filters:
    pl_filters[opt_item] = StringVar(root)
    pl_filters[opt_item].set('All')
    pl_filters[opt_item].trace('w', partial(changeplan, widget=pl_filters[opt_item]))

标签: pythonloopsvariablesoptimizationtkinter

解决方案


从您的代码的第一部分来看,您似乎正在使用traceStringVar刚才的方法将插入的字符转换为大写。如果是这样,我建议使用内置的此类方法实现您自己的类,这样您就可以避免以后创建它们。

此外,您可以在 for 循环中创建StringVar和。Entry如果需要,只需将这些引用保存在列表中以供以后使用。

import tkinter as tk

root = tk.Tk()

class CustomVar(tk.StringVar):
    def __init__(self):
        tk.StringVar.__init__(self)
        self.trace("w",self.trace_method)

    def trace_method(self,*args):
        self.set(self.get().upper())

class Something(tk.Frame):
    def __init__(self,master=None,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)
        all_vars = [CustomVar() for _ in range(5)] #create 5 vars in one go
        entries = []
        for num, var in enumerate(all_vars,1): #loop through the vars and create entries
            entry = tk.Entry(self,background="yellow",justify="center",
                             textvariable=var,width=4 if num <4 else 8)
            entries.append(entry)

        for num, cords in enumerate(((1,5),(2,5),(5,5),(0,9),(0,10))): #your grid row and column number grouped in a tuple
            entries[num].grid(column=cords[0],row=cords[1],padx=5,sticky="SEW")

a = Something(root)
a.pack()

root.mainloop()

推荐阅读