Reputation: 168
I am creating a simple entry UI to intake 2 text fields and a folder path. I'm just getting started with tkinter and I can't get the browse button to appear next to the entry field for the CSV file. Instead it appears with the other buttons.
I have read the tkinter tutorial. I've tried three different Frame ideas from coworkers and the web. I did try to put this in an element, but either my brain is fried or I'm just not good enough to understand how that works. I think grids might be my answer, but as this is the first UI I've tried like this I can't follow the code.
import tkinter as tk
fields = 'Version', 'Database Name', 'CSV File'
def fetch(entries):
for entry in entries:
field = entry[0]
text = entry[1].get()
print('%s: "%s"' % (field, text))
def callback():
path = tk.filedialog.askopenfilename()
entry.delete(0, tk.END)
entry.insert(0, path)
def initUI(root, fields):
entries = []
for field in fields:
if field == 'CSV File':
frame = tk.Frame(root)
frame.pack(fill=tk.X)
lbl = tk.Label(frame, text=field, width=20, anchor='w')
lbl.pack(side=tk.LEFT, padx=5, pady=5)
entry = tk.Entry(frame)
entry.pack(fill=tk.X, padx=5)
btn = tk.Button(root, text="Browse", command=callback)
btn.pack(side=tk.RIGHT,padx=5, pady=5)
entries.append((field, entry))
else:
frame = tk.Frame(root)
frame.pack(fill=tk.X)
lbl = tk.Label(frame, text=field, width=20, anchor='w')
lbl.pack(side=tk.LEFT, padx=5, pady=5)
entry = tk.Entry(frame)
entry.pack(fill=tk.X, padx=5, expand=True)
entries.append((field, entry))
return entries
if __name__ == '__main__':
root = tk.Tk()
root.title("Helper")
entries = initUI(root,fields)
root.bind('<Return>', (lambda event, e=entries: fetch(e)))
frame = tk.Frame(root, relief=tk.RAISED, borderwidth=1)
frame.pack(fill=tk.BOTH, expand=True)
closeButton = tk.Button(root, text="Close", command=root.quit)
closeButton.pack(side=tk.RIGHT, padx=5, pady=5)
okButton = tk.Button(root, text="OK", command=(lambda e=entries: fetch(e)))
okButton.pack(side=tk.RIGHT)
root.mainloop()
I am wanting the Browse button next to the entry field instead of its current location down with the OK and Close buttons.
Side problem... I can't figure out how to get my callback to work!
Upvotes: 4
Views: 9326
Reputation: 15513
Question: How to keep tkinter button on same row as label and entry box
To reach this you have to pack
the Entry
and Button
into a own Frame
.
Note: Use always
side=tk.LEFT
to get the widgets in a row.
This example shows a OOP
solution:
Define a class LabelEntry
inherited from tk.Frame
.
class LabelEntry(tk.Frame):
def __init__(self, parent, text, button=None):
super().__init__(parent)
self.pack(fill=tk.X)
lbl = tk.Label(self, text=text, width=14, anchor='w')
lbl.pack(side=tk.LEFT, padx=5, pady=5)
Condition: If a Button
passed, create a new Frame
to pack
the Entry
and Button
.
if button:
frame2 = tk.Frame(self)
frame2.pack(side=tk.LEFT, expand=True)
entry = tk.Entry(frame2)
entry.pack(side=tk.LEFT, fill=tk.X, padx=5)
button.pack(in_=frame2, side=tk.LEFT, padx=5, pady=5)
else:
entry = tk.Entry(self)
entry.pack(side=tk.LEFT, fill=tk.X, padx=5)
Usage:
Define a class App
inherit from tk.Tk
.
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Helper")
frame = tk.Frame(self)
frame.grid(row=0, column=0)
Loop the fields
and create a LabelEntry
object
entries = []
for field in 'Version', 'Database Name', 'CSV File':
if field == 'CSV File':
button = tk.Button(text="Browse", command=self.callback)
entries.append(LabelEntry(frame, field, button))
else:
entries.append(LabelEntry(frame, field))
Run the Application.
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5
Upvotes: 3