I want to create a widget outside his frame, but I don't know what's his master.
this is the structure.
first I created the class of the root. and then 3 classes of frames.
inside the class of the root I put a function. inside the function I created a text widget that should be located in the first one of the 3 frames
I really don't get what I should write as the master of my text widget to locate it in the first frame.
since I am a beginner if you have any advice I'd really appreciate.
thanks for attention here's the code
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
import datetime
LARGE_FONT = ("VERDANA", 12)
#user's information manager(classes and method)
class person:
def __init__(self, name, birthday, sex):
self.name = name
self.birthday = birthday
self.sex = sex
def age(self, name, birthday):
user = person(name, birthday, "male")
today = datetime.date.today()
print (today.year - self.birthday.year)
#main windows
class deathCalculatorapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "age calculator app")
container = tk.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 (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
# all methods here
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
def calculate(self, name, birthday):
user = person(name, birthday, "male")
text_answer = tk.Text(master = , height=3, width=30)
text_answer.grid(column=1, row=9)
answear_text = ("{name} is {age} years old".format(name=name_entry.get(), age=calculate()))
text_answer.insert(tk.END, answear_text)
print (user.age()
#all of the frames
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#Labels
label = ttk.Label(self, text="deathcalculatorapp", font=LARGE_FONT)
label.grid(column=1, row=0)
first_label = ttk.Label(self, text = "insert your data")
name_label= tk.Label(self, text = "name", bg="lightblue")
year_label = tk.Label(self, text="year", bg ="lightblue", padx=9)
month_label = tk.Label(self, text= "month", bg = "lightblue", padx=3)
day_label = tk.Label(self, text ="day", bg= "lightblue", padx=11)
first_label.grid(column=1, row=3)
name_label.grid(column=0, row=4)
year_label.grid(column=0, row =5)
month_label.grid(column=0, row =6)
day_label.grid(column=0, row = 7)
#Entries
name_entry = tk.Entry(self, text = "", bg = "lightblue")
year_entry = tk.Entry(self,text = "", bg = "lightblue")
month_entry = tk.Entry(self, text = "", bg= "lightblue")
day_entry = tk.Entry(self, text= "", bg = "lightblue")
name_entry.grid(column=1, row=4)
year_entry.grid(column=1,row=5)
month_entry.grid(column=1, row= 6)
day_entry.grid(column=1, row=7)
#Radiobutton about sex
sexdatum = tk.IntVar()
female= ttk.Radiobutton(self, text="female",variable= sexdatum, value="female")
male=ttk.Radiobutton(self, text="male", variable= sexdatum, value="male")
female.grid(column=2, row=4)
male.grid(column=2, row=5)
#Buttons
calculate_button = ttk.Button(self, text="calculate your lifespawn",
command=lambda: controller.age(name_entry.get(),datetime.date(int(year_entry.get()),int(month_entry.get()),int(day_entry.get()))))
calculate_button.grid(column=1, row=8)
button1 = ttk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = ttk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.grid(column=0, row=0)
button2.grid(column=0, row=1)
#text
#image
image = Image.open(r"/"
r"Users/tommasomasaracchio/Documents/pythonfolder/kushina4.jpg")
image.thumbnail((500,300), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(image)
Photo_label= ttk.Label(self, image=photo)
Photo_label.image = photo
Photo_label.grid(row= 2, column = 1)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, text="This is page 1", font=LARGE_FONT)
label.grid(column=0, row=0)
button = ttk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.grid(column=0, row=0)
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, text="This is page 2", font=LARGE_FONT)
label.grid(column=0, row=0)
button = ttk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.grid(column=0, row=0)
if __name__ == "__main__":
app = deathCalculatorapp()
app.mainloop()
It should be master = self.frames['StartPage'].
Related
I am trying to collect the date from a calendar widget in tkinter using a button and then display that date in a label, so I defined a function to do so, however, it does not work and I get the error message "getdate() missing 2 required positional arguments: 'self' and 'cont'"\
I am not sure why this is as I have included self and cont in the function brackets.
import tkinter as tk
from tkinter import ttk
from tkcalendar import *
def getdate(self, cont):
date_label.config(text="Today's date is " + cal.get_date()) #function to get date from
#calendar and display in label
#window = Tk()
#window.title("StudyFriendO")
LARGE_FONT= ("Verdana", 24)
class StudyFriendO(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("StudyFriendO") #naming window title
self.geometry('850x830') #size of window
container = tk.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 (StartPage, HomePage, ToDoPage, TimetablePage): #list of multiple frames of program
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame): #creating start page
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="StudyFriendO", font = LARGE_FONT, bg="#f2fcff")
label.pack(fill="x")
#place(x=315,y=100)
photo1 = tk.PhotoImage(file NAME') #photo1 is a variable
#label (window, image=photo1, bg="black") .grid(row=0, column=0, sticky=E)
panel = tk.Label(self, image = photo1)
panel.image = photo1
panel.pack(fill="x")
#place(x=270,y=150)
label2 = tk.Label(self, text="Enter today's date and your first name below:", bg="#f2fcff")
label2.pack(fill="x", ipady=20)
#place(x=305, y=400)
cal = Calendar(self, background="#e0f6fc", disabledbackground="white", bordercolor="light blue", headersbackground="light blue", normalbackground="#e0f6fc", foreground="black", normalforeground='black', headersforeground='white', selectmode="day", year=2021, month=8, day=9)
cal.place(relx=0.5, rely=0.5, anchor='center')
#(x=300,y=430) #calendar
nameentry = tk.Entry(self, width=20, bg="white") #text input for users name
nameentry.place(relx=0.5, rely=0.68, anchor='center')
#(x=365, y=635)
caldate = ttk.Button(self, text="Submit",
command=getdate) #button to get current date
caldate.place(relx=0.5, rely=0.63, anchor='center')
button1 = ttk.Button(self, text="Enter",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.place(relx=0.5, rely=0.73, anchor='center')
#(x=387,y=660)
date_label = tk.Label(self, text="") #label to display date
date_label.pack(pady=20)
self.configure(bg='#f2fcff')
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Home", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
class ToDoPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="To Do", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
class TimetablePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Timetable", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
app = StudyFriendO()
app.mainloop()
There were a couple of issues with the given questions.
There is no reference for date_label & cal inside the get_date() function. cal may be an import error.
Moved get_date() inside the StudyFriendO class & renamed it to set_date().
modified the way to handled this as a command from the submit button.
Have a look at the modified code & the output image.
import calendar
import tkinter as tk
from tkinter import ttk
from tkcalendar import *
from datetime import datetime
#calendar and display in label
#window = Tk()
#window.title("StudyFriendO")
LARGE_FONT= ("Verdana", 24)
class StudyFriendO(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("StudyFriendO") #naming window title
self.geometry('850x830') #size of window
container = tk.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 (StartPage, HomePage, ToDoPage, TimetablePage): #list of multiple frames of program
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def set_date(self, cont):
frame: StartPage = self.frames[cont]
frame.date_label.config(text="Today's date is " + datetime.today().strftime("%B %d, %Y")) #function to get date from
class StartPage(tk.Frame): #creating start page
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="StudyFriendO", font = LARGE_FONT, bg="#f2fcff")
label.pack(fill="x")
#place(x=315,y=100)
photo1 = tk.PhotoImage(file="1.png") #photo1 is a variable
#label (window, image=photo1, bg="black") .grid(row=0, column=0, sticky=E)
panel = tk.Label(self, image = photo1)
panel.image = photo1
panel.pack(fill="x")
#place(x=270,y=150)
label2 = tk.Label(self, text="Enter today's date and your first name below:", bg="#f2fcff")
label2.pack(fill="x", ipady=20)
#place(x=305, y=400)
cal = Calendar(self, background="#e0f6fc", disabledbackground="white", bordercolor="light blue", headersbackground="light blue", normalbackground="#e0f6fc", foreground="black", normalforeground='black', headersforeground='white', selectmode="day", year=2021, month=8, day=9)
cal.place(relx=0.5, rely=0.5, anchor='center')
#(x=300,y=430) #calendar
nameentry = tk.Entry(self, width=20, bg="white") #text input for users name
nameentry.place(relx=0.5, rely=0.68, anchor='center')
#(x=365, y=635)
caldate = ttk.Button(self, text="Submit",
command=lambda: controller.set_date(StartPage)) #button to get current date
caldate.place(relx=0.5, rely=0.63, anchor='center')
button1 = ttk.Button(self, text="Enter",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.place(relx=0.5, rely=0.73, anchor='center')
#(x=387,y=660)
self.date_label = tk.Label(self, text="") #label to display date
self.date_label.pack(pady=20)
self.configure(bg='#f2fcff')
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Home", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
class ToDoPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="To Do", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
class TimetablePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Timetable", font = LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Home",
command=lambda: controller.show_frame(HomePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="Timetable",
command=lambda: controller.show_frame(TimetablePage)) #button to navigate page
button1.pack()
button1 = ttk.Button(self, text="To Do",
command=lambda: controller.show_frame(ToDoPage)) #button to navigate page
button1.pack()
app = StudyFriendO()
app.mainloop()
Output Image:
This question already has answers here:
How to get variable data from a class?
(2 answers)
Closed 1 year ago.
I'm looking for advice on how to solve my problem. I need a way to save the entries list in my saveInput() method so I can access it later outside the class with a different function. The only solution I have come up with is a global variable but I'm told they are the devil and I should try to avoid them when they are not constant. If anybody could give me a solution I would greatly appreciate it. My code is below, including the CSV file.
from tkinter import font as tkfont # python 3
import tkinter as tk
import csv
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.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 (StartPage, PageOne, PageTwo, PageThree, PageFour):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Enter airport details",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Enter flight details",
command=lambda: controller.show_frame("PageTwo"))
button3 = tk.Button(self, text="Enter price plan and calculate profit",
command=lambda: controller.show_frame("PageThree"))
button4 = tk.Button(self, text="Clear data",
command=lambda: controller.show_frame("PageFour"))
button1.pack()
button2.pack()
button3.pack()
button4.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
ukAirportOptionList = [
"LPL",
"BOH"
]
foreignAirportList = []
with open('Airports.csv', 'r') as fd:
reader = csv.reader(fd)
for row in reader:
foreignAirportList.append(row)
tk.Label(self, text="Airport Details", font=controller.title_font).grid()
ukAirportTracker = tk.StringVar()
ukAirportTracker.set("Select the UK Airport")
tk.OptionMenu(self, ukAirportTracker, *ukAirportOptionList).grid()
foreignAirportTracker = tk.StringVar()
foreignAirportTracker.set("Select the Oversea Airport")
tk.OptionMenu(self, foreignAirportTracker, *[airport[0] for airport in foreignAirportList]).grid()
saveButton = tk.Button(self, text="Save",
command=lambda: [controller.show_frame("StartPage"),
self.saveInput(ukAirportTracker, foreignAirportTracker)])
saveButton.grid(row=3, column=1)
def saveInput(self, *args):
enteries = []
for arg in args:
enteries.append(arg.get())
print(enteries)
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
aircraftTypesList = [['medium narrow body', 8, 2650, 180, 8],
['large narrow body', 7, 5600, 220, 10],
['medium wide body', 5, 4050, 406, 14]]
label = tk.Label(self, text="Flight Details", font=controller.title_font)
label.grid()
aircraftTypeTracker = tk.StringVar()
aircraftTypeTracker.set("Aircraft Type")
tk.OptionMenu(self, aircraftTypeTracker, *[aircraft[0] for aircraft in aircraftTypesList]).grid()
saveButton = tk.Button(self, text="Save",
command=lambda: [controller.show_frame("StartPage"), self.saveInput(aircraftTypeTracker)])
saveButton.grid()
def saveInput(self, *args):
enteries = []
for arg in args:
enteries.append(arg.get())
print(enteries)
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Label(self, text="This is page 3", font=controller.title_font).grid(row=0, column=0)
tk.Label(self, text="Price of Standard Seat").grid(row=1)
tk.Label(self, text="Price of First Class Seat").grid(row=2)
e1 = tk.Entry(self)
e2 = tk.Entry(self)
e1.grid(row=1, column=1)
e2.grid(row=2, column=1)
saveButton = tk.Button(self, text="Save",
command=lambda: [controller.show_frame("StartPage"), self.saveInput(e1, e2)])
saveButton.grid(row=3, column=1)
def saveInput(self, *args):
enteries = []
for arg in args:
enteries.append(arg.get())
print(enteries)
class PageFour(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 4", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
The csv file:
JFK,John F Kennedy International,5326,5486
ORY,Paris-Orly,629,379
MAD,Adolfo Suarez Madrid-Barajas,1428,1151
AMS,Amsterdam Schiphol,526,489
CAI,Cairo International,3779,3584
A way to mostly✶ avoid global variables in this case is to make the local variable enteries an instance attribute of some class. In this case I chose the SampleApp "controller" this tkinter app architecture defines. (Note I also changed its name to entries in the modified code below.)
✶ I say that because it's very difficult to not have any.
Disclaimer: I don't quite understand what you want or are planning to put into the enteries list in each Page class of you code, so the results below merely do the same as in your code. I'm also not sure what you mean by "returning variables" because classes are objects and don't return anything per se. They can be containers of data and have methods that return values — but you don't have any examples of that in your question's code. To rectify that I added a Quit button to demonstrate how the data could be retrieved.
Anyway, I made the modifications needed to do that in code below. In addition, I noticed there was a lot of replicated / very similar code in each Page class, so I defined a private base class named _BasePage and derived all the others from it. This allowed me to put the common code in there and is an example of apply the DRY principle which is another benefit of using classes.
from tkinter import font as tkfont # python 3
import tkinter as tk
import csv
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold",
slant="italic")
self.entries = [] # Accumulated entries.
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.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 (StartPage, PageOne, PageTwo, PageThree, PageFour):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name.'''
frame = self.frames[page_name]
frame.tkraise()
class _BasePage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
def saveInput(self, *string_vars):
strings = [var.get() for var in string_vars]
print(f'adding entries: {strings}')
self.controller.entries.extend(strings)
class StartPage(_BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
tk.Button(self, text="Enter airport details",
command=lambda: controller.show_frame("PageOne")).pack()
tk.Button(self, text="Enter flight details",
command=lambda: controller.show_frame("PageTwo")).pack()
tk.Button(self, text="Enter price plan and calculate profit",
command=lambda: controller.show_frame("PageThree")).pack()
tk.Button(self, text="Clear data",
command=lambda: controller.show_frame("PageFour")).pack()
tk.Button(self, text="Quit",
command=self.quit).pack() # Terminate mainloop().
class PageOne(_BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
ukAirportOptionList = [
"LPL",
"BOH"
]
foreignAirportList = []
with open('Airports.csv', 'r') as fd:
reader = csv.reader(fd)
for row in reader:
foreignAirportList.append(row)
tk.Label(self, text="Airport Details", font=controller.title_font).grid()
ukAirportTracker = tk.StringVar()
ukAirportTracker.set("Select the UK Airport")
tk.OptionMenu(self, ukAirportTracker, *ukAirportOptionList).grid()
foreignAirportTracker = tk.StringVar()
foreignAirportTracker.set("Select the Oversea Airport")
tk.OptionMenu(self, foreignAirportTracker,
*[airport[0] for airport in foreignAirportList]).grid()
saveButton = tk.Button(self, text="Save", command=lambda:
[controller.show_frame("StartPage"),
self.saveInput(ukAirportTracker, foreignAirportTracker)])
saveButton.grid(row=3, column=1)
class PageTwo(_BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
aircraftTypesList = [['medium narrow body', 8, 2650, 180, 8],
['large narrow body', 7, 5600, 220, 10],
['medium wide body', 5, 4050, 406, 14]]
label = tk.Label(self, text="Flight Details", font=controller.title_font)
label.grid()
aircraftTypeTracker = tk.StringVar()
aircraftTypeTracker.set("Aircraft Type")
tk.OptionMenu(self, aircraftTypeTracker,
*[aircraft[0] for aircraft in aircraftTypesList]).grid()
saveButton = tk.Button(self, text="Save", command=lambda:
[controller.show_frame("StartPage"),
self.saveInput(aircraftTypeTracker)])
saveButton.grid()
class PageThree(_BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
tk.Label(self, text="This is page 3",
font=controller.title_font).grid(row=0, column=0)
tk.Label(self, text="Price of Standard Seat").grid(row=1)
tk.Label(self, text="Price of First Class Seat").grid(row=2)
e1 = tk.Entry(self)
e2 = tk.Entry(self)
e1.grid(row=1, column=1)
e2.grid(row=2, column=1)
saveButton = tk.Button(self, text="Save",
command=lambda: [controller.show_frame("StartPage"),
self.saveInput(e1, e2)])
saveButton.grid(row=3, column=1)
class PageFour(_BasePage):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label = tk.Label(self, text="This is page 4", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
print('Final entries:')
for entry in app.entries:
print(f' {entry}')
In my code, there are two frames. In the first one, I put in an Add button that will produce a new frame with a Combobox. The idea is to add a few Combobox like that in the first frame, pick different options for different Combobox, and then print them out in the next frame. But when I hit the Show options button in the second frame, it doesn't print out the options that I just chose in the first frame. How can I solve this?
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(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 (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def add_compare():
global list_1
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
self.options_1 = ttk.Combobox(frame, values=['a','b','c','d','e'])
self.options_1.grid(row=1, column=0)
list_1.append(self.options_1.get())
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add', command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
Here's a modified version of your code that will print the options selected so far when the Next is pressed. To prevent the Comboboxes from interferring with each other a list of them and an associated StringVars is kept.
Having separate StringVars avoids the problem of choosing an option on one of them from changing it on the others — i.e. a different textvar gets associated with each one.
To make collecting all the options together into list_1, a callback function named selected() has been defined and gets "bound" to Combobox selection events. This make it so that, in addition to the above, the option selected will also get appended to the global list_1, which is what the Show options button displays.
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(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.comboboxes = [] # Comboboxes created. ADDED
self.combobox_vars = [] # Vars for Comboboxes. ADDED.
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
# Combobox event handler. ADDED
def selected(event, var):
list_1.append(var.get()) # Append Combobox option selected.
def add_compare():
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
combobox_var = StringVar() # ADDED.
combobox = ttk.Combobox(frame, values=list('abcde'),
textvar=combobox_var) # For each Combobox. ADDED.
combobox.grid(row=1, column=0)
combobox.bind('<<ComboboxSelected>>', # Bind event handler. ADDED.
lambda event, var=combobox_var: selected(event, var)) # ADDED.
self.controller.comboboxes.append(combobox) # ADDED.
self.controller.combobox_vars.append(combobox_var) # ADDED.
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add',
command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
I am VERY new to coding/Python, but basically I am trying to move a button and label around using .grid, however, the button and label in the StartPage class just won't move to where I ask (or even at all).
Everything in the BMR class works fine (although the positions you see aren't the final positions, I was just checking).
What is the difference? Why do they not appear at the same position if I give the same details in both classes?
import tkinter as tk
class initials(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.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 (StartPage, BMR):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky='nsew')
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame): #GRID WON'T WORK HOW I WANT IT TO
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Start Page")
label.grid(column=3, row=3, sticky='we')
button = tk.Button(self, text="Calculate BMR",
command=lambda: controller.show_frame(BMR))
button.grid(row=4, column=3, sticky='we')
class BMR(tk.Frame): #GRID WORKS PERFECTLY
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="BMR Calculator")
label.grid(column=1,row=1)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.grid(column=2, row=2)
submit = tk.Button(self, text="Calculate")
submit.grid(column=3, row=3)
var1 = tk.IntVar()
tk.Checkbutton(self, text='Male', bg='white', variable=var1).grid(column=4, row=4)
var2= tk.IntVar()
tk.Checkbutton(self, text='Female', bg='white', variable=var2).grid(column=5, row=5)
height_inp = tk.Entry(self, width=20, bg="white").grid(column=6, row=6)
app = initials()
app.mainloop()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Start Page", width = 80)
# Added width property in the line above
# and changed sticky property to N
label.grid(row = 3, column=3, sticky = 'N')
label.width = 20
button = tk.Button(self, text="Calculate BMR",
command=lambda: controller.show_frame(BMR))
button.grid(row=4, column=3)
# Removed sticky property for the button
I understand this is how you wish to position the label and the button.
Pleaase see the comments. You can edit the value for the width property and make it suitable for your frame.
This question already has answers here:
How to get variable data from a class?
(2 answers)
Closed 6 years ago.
my program is this..
import tkinter as tk
from tkinter import *
TITLE_FONT = ("Helvetica", 18, "bold")
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
self.title(" Allocation")
width, height = self.winfo_screenwidth(), self.winfo_screenheight()
self.geometry('%dx%d+0+0' % (width,height))
self.state('zoomed')
self.wm_iconbitmap('icon.ico')
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 (StartPage, PageOne, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
logo = tk.PhotoImage(file="backesh.ppm")
BGlabel = tk.Label(self,image=logo)
BGlabel.image = logo
BGlabel.place(x=0,y=0,width=592,height=450)
label = tk.Label(self, text="This is the start page", font=TITLE_FONT)
label.place(x=0,y=0,width=592,height=44)
frame1 = Frame(self)
Label(frame1, bd=5,bg="black",text=" Enter text : ",font=("Helvetica", 14),fg="light green",width=21).pack(side=LEFT)
emp=Entry(frame1, bd =5,font=("Times New Roman", 14),width=25)
emp.pack(side=LEFT)
frame1.place(x=400,y=160)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame(PageOne))
button2 = tk.Button(self, text="Go to Page two",
command=lambda: controller.show_frame(PageTwo))
button3 = tk.Button(self, text="Exit",
command=self.quit)
button1.place(x=100,y=406,width=200,height=44)
button2.place(x=300,y=406,width=200,height=44)
button3.place(x=500,y=406,width=80,height=44)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
logo = tk.PhotoImage(file="backesh.ppm")
BGlabel = tk.Label(self,image=logo)
BGlabel.image = logo
BGlabel.place(x=0,y=0,width=592,height=450)
label = tk.Label(self, text="This is page one", font=TITLE_FONT)
label.place(x=0,y=0,width=592,height=44)
button1 = tk.Button(self, text="Go to Start Page",
command=lambda: controller.show_frame(StartPage))
#button2 = tk.Button(self, text="Go to Page two",
# command=lambda: controller.show_frame(PageTwo))
button3 = tk.Button(self, text="Exit",
command=self.quit)
button1.place(x=100,y=406,width=200,height=44)
button3.place(x=300,y=406,width=200,height=44)
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
logo = tk.PhotoImage(file="backesh.ppm")
BGlabel = tk.Label(self,image=logo)
BGlabel.image = logo
BGlabel.place(x=0,y=0,width=592,height=450)
label = tk.Label(self, text="This is page two", font=TITLE_FONT)
label.place(x=0,y=0,width=592,height=44)
button1 = tk.Button(self, text="Go to Start Page",
command=lambda: controller.show_frame(StartPage))
#button2 = tk.Button(self, text="Go to Page two",
# command=lambda: controller.show_frame(PageTwo))
button3 = tk.Button(self, text="Exit",
command=self.quit)
button1.place(x=100,y=406,width=200,height=44)
button3.place(x=300,y=406,width=200,height=44)
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
i want to take entry text data from StartPage and display it as label in PageOne. How to do it? I am new to this. Please type the code.
Thanks in advance.
Firstly, correct the code of the class PageOne and StartPage and add self.controller = controller to the __init__ function:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
#your code
self.controler = controller
Add self before entry field in StartPage and before label in PageOne:
#entry in StartPage
self.emp=tk.Entry(frame1, bd =5,font=("Times New Roman", 14),width=25)
self.emp.pack(side=tk.LEFT)
#label in PageOne
self.label = tk.Label(self, text="This is page one", font=TITLE_FONT)
self.label.place(x=0,y=0,width=592,height=44)
Then add a function go_to_page_one to StartPage class:
def go_to_page_one(self):
self.controller.SomeVar = self.emp.get() #save text from entry to some var
self.controller.frames[PageOne].correct_label() #call correct_label function
self.controller.show_frame(PageOne) #show page one
On button1 in StartPage class change command to lambda: self.go_to_page_one():
button1 = tk.Button(self, text="Go to Page One",
command=lambda: self.go_to_page_one())
At last add a function correct label to the class PageOne:
def correct_label(self):
self.label.config(text=self.controller.SomeVar) #correct the label