Reputation: 477
I am creating a program with two frames in one window. The first has input fields, the second will create a graph. I found a way to create input fields dynamically from a list and get their values accordingly, but I can't get them to show on the window. When I run the program it shows an empty window.
What should I do to get the label and input widgets to show on the first frame (InputPage)? I tried changing 'parent' to 'self' but it made no difference. I don't really understand the structure of widgets in multiple frame applications.
Here is my code:
from tkinter import *
namesInput = ["first", "second", "third", "fourth", "fifth"]
entryInput = {}
labelInput = {}
root = Tk()
class ZorgplanGrafiek(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (InputPage, GraphPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(InputPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class InputPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self,parent)
label = Label(self, text="Zorgplan input")
label.pack(pady=10,padx=10)
i = 0
for name in namesInput:
e = Entry(self)
entryInput[name] = e
lb = Label(self, text=name)
labelInput[name] = lb
i += 1
#def print_all_entries():
# for name in namesInput:
# print( entryInput[name].get())
class GraphPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
label = Label(self, text="The graph will show here")
label.pack(pady=10,padx=10)
button = Button(self, text="Back to Home",
command=lambda: controller.show_frame(InputPage))
button.pack()
app = ZorgplanGrafiek()
app.mainloop()
Upvotes: 2
Views: 5985
Reputation: 810
Firstly delete root = Tk() at the top of your code you are creating 2 windows. Secondly, your loop to create the entry and label widgets is not correct therefore they are not displayed on the frame, so that is your answer for why they wont show.
Try this:
class InputPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self,parent)
label = Label(self, text="Zorgplan input")
label.grid(row=0, column=0, sticky ='n', columnspan =2)
# i brought your variable in the class for example sake
namesInput = ["First:", "second:", "Third:", "Fourth:", "Fifth:"]
self.entryWidgets = [] # we want to call this in another function so we assign it as self.variableName
labelWidgets = []
#LOOP TO CREATE WIDGETS
for i in range(0, len(namesInput)):
labelWidgets.append(Label(self, text = namesInput[i]))
self.entryWidgets.append(Entry(self))
labelWidgets[-1].grid(row= i+1, column =0, sticky='e')
self.entryWidgets[-1].grid(row= i+1, column = 1, sticky='w')
submit = Button(self, text = "Submit", command = self.getEntries)
submit.grid(row = 6, column =0, columnspan =2)
def getEntries(self):
results = []
for x in self.entryWidgets: # i.e for each widget in entryWidget list
results.append(x.get())
print(results)
Code explanation:
We are iteratively creating widgets to the number of elements within namesInput list. Each time we create a widget we add it to their respective list. E.g for entry widgets we created a list called entryWidgets. We append them to a list so that we can reference them individually later on when we want to do something with them.
Furthermore, i changed pack() to grid(). The grid method is much cleaner and gives us more control over the layout of our window in my opinion.
Note - If you're struggling to understand how i 'grided' the widgets in the way i did, i just drew up a quick sketch of the widgets with co-ordinates representing their row and column and then from there its fairly easy to see how to manipulate the grid settings in the for loop.
Upvotes: 4