Python 如何在tkinter中创建循环中的按钮、文本框和标签

Python 如何在tkinter中创建循环中的按钮、文本框和标签,python,tkinter,Python,Tkinter,我试图创建一个框架来创建一个标签,文本框和按钮作为一个对象,我可以很容易地扩展它 想法: 如果它有更多的文件,它可以扩展到3、4、5或更多,只要在字典列表中声明,它就会自动扩展 我的守则如下: def getpath(entry_box, type): # path or file if type == 'path': entry_box.set(filedial.askdirectory()) elif type == 'file': entry_box.set(filed

我试图创建一个框架来创建一个标签,文本框和按钮作为一个对象,我可以很容易地扩展它

想法:

如果它有更多的文件,它可以扩展到3、4、5或更多,只要在字典列表中声明,它就会自动扩展

我的守则如下:

def getpath(entry_box, type):
# path or file
if type == 'path':
    entry_box.set(filedial.askdirectory())
elif type == 'file':
    entry_box.set(filedial.askopenfilename())

MainWin = tk.Tk() # Create main windows
MainWin.title('Get file and path') # App name

# Create root container to hold Frames
mainFrame = ttk.Frame(MainWin)
mainFrame.grid(column=1, row=1)
# define the object to create in dictionary, format:
# {object name:[title name, default path, button name, file or folder path]}
obj2create ={'file1':['ABC Location: ', r'C:/', 'Get ABC','file'],
             'file2': ['DEF Location:', r'C:/1/', 'Get DEF', 'file']}
ttl_obj = 0
for key in obj2create:
    ttl_obj +=1
    vir = obj2create[key]
    # Module for get file:
    obj_name = key
    title = vir[0]
    default_path = vir[1]
    btn_name = vir[2]
    get_type = vir[3]

    # Create main container
    pa_frame = ttk.Frame(mainFrame)
    pa_frame.grid(column=1, row=10*ttl_obj, sticky=tk.W)
    pa_frame.config(width = 100)
    # Row 1: Label
    frame_name = obj_name + '_name'
    print(frame_name)
    frame_name = ttk.Label(pa_frame, text= title).grid(column=1, row=10*ttl_obj,sticky=tk.W)
    # Row 2: path and button
    # assign type
    path_loc = obj_name + '_path'
    path_loc = tk.StringVar()
    path_loc.set(default_path)
    # put in frame
    fileLocPath = obj_name + '_loc_path'
    fileLocPath = ttk.Entry(pa_frame, width=70, textvariable=path_loc)
    fileLocPath.grid(column=1, row=30*ttl_obj) # Assign position
    # Get file button
    # define button display text and assign the command / function
    bt_get_file_path = obj_name + '_btn'
    bt_get_file_path = ttk.Button(pa_frame, text= btn_name,
                                  command=lambda: getpath(path_loc, get_type))
    # Position Button in second row, second column (zero-based)
    bt_get_file_path.grid(column=2, row=30*ttl_obj)


# Auto popup when open
MainWin.mainloop() # Let the window keep running until close
问题:

  • 默认文件路径仅显示在第二个文本框中

  • 所有按钮位置都指向第二个框

  • 我也不知道如何才能在不同的框中获得值,“path_loc=obj_name+'_path'”无法获得正确的对象


    我该怎么做?或者我使用的方法是错误的?

    Tkinter小部件与任何其他python对象在循环中创建它们方面没有什么不同。您的问题似乎是不知道如何为未知数量的小部件创建唯一变量

    需要知道的重要一点是,每个小部件不需要唯一的变量。相反,您可以使用列表或字典,它们中的任何一个都可以在运行时轻松扩展

    在字典中保存小部件引用 下面是一个使用字典的解决方案:

    entries = {}
    for key in obj2create:
        ...
        entries[key] = ttk.Entry(...)
        ...
    ...
    print("the value for file1 is", entries["file1"].get()
    
    创建自定义复合小部件 如果您想要创建一组要作为一个组处理的小部件,那么最好创建一个类。实际上,您正在创建自己的自定义小部件。这种类型的类通常称为“复合小部件”或“megawidget”

    例如:

    class FileWidget(ttk.Frame):
        def __init__(self, parent, name):
            ttk.Frame.__init__(self, parent)
            self.label = ttk.Label(self, text="%s Location" % name)
            self.fileLocPath = ttk.Entry(self)
            self.bt_get_file_path = ttk.Button(self, text=name, command=self.get_path)
            ...
    
        def get_path(self):
            return self.fileLocPath.get()
    
    然后,您可以在GUI中创建每一行,如下所示:

    widgets = {}
    for key in obj2create:
        widgets[key] = FileWidget(mainFrame, key)
        widgets[key].pack(side="top", fill="x")
    
    for key in obj2create:
        widget = widgets[key]
        print("%s: %s" % (key, widget.get_path())
    
    稍后,您可以返回如下值:

    widgets = {}
    for key in obj2create:
        widgets[key] = FileWidget(mainFrame, key)
        widgets[key].pack(side="top", fill="x")
    
    for key in obj2create:
        widget = widgets[key]
        print("%s: %s" % (key, widget.get_path())
    

    如果我理解这一点,您希望在循环中以不同的方式命名每个小部件,但您不能这样做,对吗?是的,因为我需要知道文件ABC和DEF的位置。文件选择器也不起作用,当我按“Get ABC”时,它会更新到DEF文件路径中的文本框。我们使用字典(或列表)来实现这一点-即,
    path\u loc[obj\u name]=…
    Tks,它确实起作用,我认为这是一个进步,需要时间来理解。