How to create buttons, text boxes and label in loop in tkinter
<p>I am trying to create a framework to create a label, text box and button as an object, I can extend it easily.</p>

<p>Idea:</p>

<p><a href="http://i.stack.imgur.com/gsSAR.png" rel="nofollow">Original</a></p>

<p><a href="http://i.stack.imgur.com/x8q8C.png" rel="nofollow">after extend</a></p>

<p>and it could extend to have 3, 4, 5 or more if it have more file, just declare in dictionary list, it will extend automatically. </p>

<p>The code I have:</p>

<pre><code>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
</code></pre>

<p><strong>Issue:</strong></p>

<ol>
<li><p>Default file path appear in second text box only.</p></li>
<li><p>All the button location point to second box.</p></li>
</ol>

<p>I also not sure how could I get the value in different box, the "path_loc = obj_name + '_path'" not able to get the correct object.</p>

<p>How should I make it work? Or the way I use is wrong?</p>

<p>Tkinter widgets are no different than any other python objects with respect to creating them in a loop. Your problem seems to be that you don't know how to create a unique variable for an unknown number of widgets. </p>

<p>The important thing to know is that you don't need a unique variable for each widget. Instead, you can use a list or dictionary, either of which can be easily extended at runtime. </p>

<h2>Saving widget references in a dictionary</h2>

<p>Here is a solution using a dictionary:</p>

<pre><code>entries = {}
for key in obj2create:
    ...
    entries[key] = ttk.Entry(...)
    ...
...
print("the value for file1 is", entries["file1"].get()
</code></pre>

<h2>Creating a custom compound widget</h2>

<p>If you're wanting to create sets of widgets that are to be treated as a group, it may be better to create a class. In effect, you're creating your own custom widget. This type of class is often called a "compound widget" or "megawidget". </p>

<p>For example:</p>

<pre><code>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()
</code></pre>

<p>You can then create each row in your GUI like this:</p>

<pre><code>widgets = {}
for key in obj2create:
    widgets[key] = FileWidget(mainFrame, key)
    widgets[key].pack(side="top", fill="x")
</code></pre>

<p>Later, you can get back the values like this:</p>

<pre><code>for key in obj2create:
    widget = widgets[key]
    print("%s: %s" % (key, widget.get_path())
</code></pre>

python tkinter