How to link two classes from two different python files - python

So I'm building a website for my school project using tkinter (specifically customtkinter). What i want to achieve is that when I click the manager button on the main window, the manager window to open up. The main window and manager window exist in two different python files. Unfortunately its been nothing but errors for the past 5 hours for me.
Below is the code for the main window
from tkinter import *
from tkinter import messagebox,ttk
from PIL import ImageTk, Image
import Py_SQL_conn as PS
import tkinter.messagebox
import customtkinter
from customtkinter import *
from tkcalendar import Calendar, DateEntry
from datetime import date
from datetime import datetime
import trailtk19 as tr
#try to increase window size...
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
class SampleApp(customtkinter.CTk):
def __init__(self, *args, **kwargs):
customtkinter.CTk.__init__(self, *args, **kwargs)
# 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 = CTkFrame(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,Booking_page,Ava_Sch_page,Passenger_page):
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 Booking_page(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
self.controller = controller
main_frame=CTkFrame(master=self)
main_frame.pack(fill=BOTH, expand=1)
but1=CTkButton(master=main_frame,width=190,text="Main",command=lambda: controller.show_frame("StartPage"))
but1.pack(side=LEFT,pady=0,padx=0)
but2=CTkButton(master=main_frame,width=190,text="See sch",command=lambda: controller.show_frame("Ava_Sch_page"))
but2.pack(side=LEFT,pady=0,padx=0)
class Ava_Sch_page(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
self.controller = controller
frame1 = CTkFrame(master=self)
frame1.pack(fill=BOTH, expand=1)
my_canvas = Canvas(frame1)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
ctk_textbox_scrollbar = customtkinter.CTkScrollbar(frame1, command=my_canvas.yview)
ctk_textbox_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=ctk_textbox_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
main_frame=CTkFrame(my_canvas,width=1300,height=2000+1000,fg_color="white")
main_frame.pack()
my_canvas.create_window((0,0), window=main_frame, anchor="nw")
header=CTkFrame(main_frame,width=1300,height=55,corner_radius=0,fg_color="#57a1f8")
header.place(x=0,y=0)
man_lab=CTkLabel(header,text="Welcome Manager",bg='white',text_font=('Microsoft YaHei UI Light',23))
man_lab.place(x=10,y=6)
#Navigation bar
nav_frame=CTkFrame(main_frame,width=925,corner_radius=0,fg_color="#1f6aa5",height=35)
nav_frame.place(x=0,y=55)
but1=CTkButton(nav_frame,text="Bookings",fg_color="#144870",corner_radius=0,height=35,width=90,state=DISABLED,command=lambda: controller.show_frame("Book_det"))
but1.pack(side=LEFT,pady=0,padx=0)
but2=CTkButton(nav_frame,text="Passengers",corner_radius=0,height=35,width=100,state=DISABLED,command=lambda: controller.show_frame("Pass_det"))
but2.pack(side=LEFT,pady=0,padx=0)
but3=CTkButton(nav_frame,text='',corner_radius=0,height=35,width=1000,state=DISABLED)
but3.pack(side=LEFT,pady=0,padx=0,fill=BOTH)
path = "aurora.jpeg"
self.img = ImageTk.PhotoImage(Image.open(path))
Label(master=main_frame,image=self.img,height=650,width=510).place(x=500,y=50)
customtkinter.CTkButton(master=main_frame,width=190,text="Booking",command=lambda: controller.show_frame("Booking_page")).place(x=1000,y=150)
customtkinter.CTkButton(master=main_frame,width=190,text="details",command=lambda: controller.show_frame("Passenger_page")).place(x=1000,y=1950)
class Passenger_page(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
self.controller = controller
main_frame=CTkFrame(master=self)
main_frame.pack(fill=BOTH, expand=1)
customtkinter.CTkButton(master=main_frame,width=190,text="Avail",command=lambda: controller.show_frame("Ava_Sch_page")).pack(side=LEFT,pady=0,padx=0)
customtkinter.CTkButton(master=main_frame,width=190,text="Main",command=lambda: controller.show_frame("StartPage")).pack(side=LEFT,pady=0,padx=0)
class StartPage(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
self.controller = controller
def confirm():
global na
u=user.get()
p=passw.get()
datsum=PS.connectorconn("Select * from managers;")
for x in datsum:
if (u==x[3]) and (p==x[4]):
con="yes"
break
else:
con="yes"
if con=="yes":
controller.show_frame("Booking_page")
#Website opens into booking page
frame1 = CTkFrame(master=self)
frame1.pack(fill=BOTH, expand=1)
# Create A Canvas
my_canvas = Canvas(frame1)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
# Add A Scrollbar To The Canvas
ctk_textbox_scrollbar = customtkinter.CTkScrollbar(frame1, command=my_canvas.yview)
ctk_textbox_scrollbar.pack(side=RIGHT, fill=Y)
##my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
##my_scrollbar.pack(side=RIGHT, fill=Y)
# Configure The Canvas
my_canvas.configure(yscrollcommand=ctk_textbox_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
# Create ANOTHER Frame INSIDE the Canvas
main_frame=CTkFrame(my_canvas,width=1300,height=2000)
main_frame.pack()
# Add that New frame To a Window In The Canvas
my_canvas.create_window((0,0), window=main_frame, anchor="nw")
#Code for scroll bar ends here. To use again, copy paste the above code and when adding widgets to the frame, make sure to put master=mainframe.
#NOTE: Only use place geometry manager to add subsequent widgets.
header=CTkFrame(main_frame,width=1300,height=55,corner_radius=0,fg_color="#57a1f8")
header.place(x=0,y=55)
man_lab=CTkLabel(header,text=" ",bg='white',text_font=('Microsoft YaHei UI Light',23))
man_lab.place(x=10,y=6)
#Navigation bar
nav_frame=CTkFrame(main_frame,width=925,corner_radius=0,fg_color="#1f6aa5",height=35)
nav_frame.place(x=0,y=108)
but=CTkButton(nav_frame,text="Schedule",corner_radius=0,height=35,state=DISABLED,command=lambda: controller.show_frame("Pass_det"))
but.pack(side=LEFT,pady=0,padx=0)
but1=CTkButton(nav_frame,text="Book flight",fg_color="#144870",corner_radius=0,height=35,state=DISABLED,command=lambda: controller.show_frame("Book_det"))
but1.pack(side=LEFT,pady=0,padx=0)
but2=CTkButton(nav_frame,text="View ticket",corner_radius=0,height=35,state=DISABLED,command=lambda: controller.show_frame("Booking_page"))
but2.pack(side=LEFT,pady=0,padx=0)
but3=CTkButton(nav_frame,text="Cancel ticket",corner_radius=0,height=35,state=DISABLED,command=lambda: controller.show_frame("Booking_page"))
but3.pack(side=LEFT,pady=0,padx=0)
but4=CTkButton(nav_frame,text="About us",corner_radius=0,height=35,state=DISABLED,command=lambda: controller.show_frame("Booking_page"))
but4.pack(side=LEFT,pady=0,padx=0)
def y():
tr.Display()
but5=CTkButton(nav_frame,text="Manager Log",corner_radius=0,height=35,command=lambda: y)
but5.pack(side=LEFT,pady=0,padx=0)
but6=CTkButton(nav_frame,text='',corner_radius=0,height=35,width=1000,state=DISABLED)
but6.pack(side=LEFT,pady=0,padx=0,fill=BOTH)
root=SampleApp()
root.title("Main_window")
root.attributes('-fullscreen',True)
root.resizable(False,False)
root.configure(bg="white")
def on_closing():
if messagebox.askokcancel("Quit", "Do you want to quit?"):
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
And below is the manger window
from tkinter import *
from tkinter import messagebox,ttk
from PIL import ImageTk, Image
import Py_SQL_conn as PS
import tkinter.messagebox
import customtkinter
from customtkinter import *
#try to increase window size...
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
class SampleApp(customtkinter.CTk):
def __init__(self, *args, **kwargs):
customtkinter.CTk.__init__(self, *args, **kwargs)
# 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 = CTkFrame(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,Book_det,Pass_det):
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(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
self.controller = controller
def confirm():
global na
u=user.get()
p=passw.get()
datsum=PS.connectorconn("Select * from managers;")
#error if not in datsum and then the stuff i guess....good prgress
for x in datsum:
if (u==x[3]) and (p==x[4]):
con="yes"
break
else:
con="no"
if con=="yes":
controller.show_frame("Book_det")
else:
messagebox.showwarning("Warning","Invalid Credentials.")
main_frame=CTkFrame(master=self)
main_frame.pack(fill=BOTH, expand=1)
path = "aurora.jpeg"
self.img = ImageTk.PhotoImage(Image.open(path))
Label(master=main_frame,image=self.img,height=650,width=510).place(x=85,y=50)
frame=CTkFrame(master=main_frame,width=350,height=350,bg="white")
frame.place(x=480,y=83)
heading=CTkLabel(master=frame,text="Manager Login",fg="#57a1f8",bg='white',text_font=('Microsoft YaHei UI Light',23))
heading.place(x=61,y=25)
#username
user= CTkEntry(master=frame,width=290,placeholder_text="Username", border=0,bg='white',text_font=('Microsoft YaHei UI Light',11))
user.place(x=30,y=120)
##user.bind('<FocusIn>',on_enter)
##user.bind('<FocusOut>',on_leave)
##CTkFrame(master=frame,width=295,bg='black').place(x=25,y=107)
#Password
passw= customtkinter.CTkEntry(master=frame,width=290,placeholder_text="Password",bg='white',border=0,text_font=('Microsoft YaHei UI Light',11))
passw.place(x=30,y=180)
##passw.bind('<FocusIn>',on_enter)
##passw.bind('<FocusOut>',on_leave)
##CTkFrame(master=frame,width=295,bg='black').place(x=25,y=177)
#Submit button
customtkinter.CTkButton(master=frame,width=190,text="Log in",command=lambda: confirm()).place(x=80,y=270)
class Book_det(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
#For every frame...
self.controller = controller
main_frame1=CTkFrame(master=self)
main_frame1.pack(fill=BOTH, expand=1)
header=CTkFrame(main_frame1,width=925,height=55,corner_radius=0,fg_color="#57a1f8")
header.pack()
man_lab=CTkLabel(header,text="Welcome Manager",bg='white',text_font=('Microsoft YaHei UI Light',23))
man_lab.place(x=10,y=6)
nav_frame=CTkFrame(main_frame1,width=925,corner_radius=0,fg_color="#1f6aa5",height=35)
nav_frame.pack(anchor="w",fill=BOTH)
but1=CTkButton(nav_frame,text="Bookings",fg_color="#144870",corner_radius=0,height=35,width=90,command=lambda: controller.show_frame("Book_det"))
but1.pack(side=LEFT,pady=0,padx=0)
but2=CTkButton(nav_frame,text="Passengers",corner_radius=0,height=35,width=100,command=lambda: controller.show_frame("Pass_det"))
but2.pack(side=LEFT,pady=0,padx=0)
but3=CTkButton(nav_frame,text='',corner_radius=0,height=35,width=1000,state=DISABLED)
but3.pack(side=LEFT,pady=0,padx=0,fill=BOTH)
fs_frame = CTkFrame(main_frame1)
fs_frame.pack(fill=BOTH,expand=1,pady=25,padx=25)
# fs_frame.pack()
reg_dep = ttk.Treeview(fs_frame,height=18)
reg_dep['columns'] = ('BookingID', 'Dep_Des_Code', 'Arr_Des_Code', 'Passenger_ID','Departure_Date','Return_Date','Booked_Seat')
reg_dep.column("#0", width=0, stretch=NO)
reg_dep.column('BookingID',anchor=CENTER, width=120)
reg_dep.column('Dep_Des_Code',anchor=CENTER, width=140)
reg_dep.column('Arr_Des_Code',anchor=CENTER,width=140)
reg_dep.column('Passenger_ID',anchor=CENTER,width=140)
reg_dep.column('Departure_Date',anchor=CENTER,width=160)
reg_dep.column('Return_Date',anchor=CENTER,width=160)
reg_dep.column('Booked_Seat',anchor=CENTER,width=140)
reg_dep.heading("#0",text="",anchor=CENTER)
reg_dep.heading('BookingID',text='BookingID',anchor=CENTER)
reg_dep.heading('Dep_Des_Code',text='Dep_Des_Code',anchor=CENTER)
reg_dep.heading('Arr_Des_Code',text='Arr_Des_Code',anchor=CENTER)
reg_dep.heading('Passenger_ID',text='Passenger_ID',anchor=CENTER)
reg_dep.heading('Departure_Date',text='Departure_Date',anchor=CENTER)
reg_dep.heading('Return_Date',text='Return_Date',anchor=CENTER)
reg_dep.heading('Booked_Seat',text='Booked_Seat',anchor=CENTER)
import mysql.connector as mycon
conn=mycon.connect(host="localhost",user="root",passwd="12345678",database="aurora_airlines")
cursor=conn.cursor()
cursor.execute("Select * from bookings;")
data=cursor.fetchall()
Records=[]
for row in data:
Records.append(row)
count=cursor.rowcount
for iid in range(count):
reg_dep.insert(parent='',index='end',iid=iid,text='',
values=(Records[iid][0],Records[iid][1],Records[iid][2],Records[iid][3], Records[iid][4],Records[iid][5],Records[iid][6]))
reg_dep.pack(pady=85)
## button = customtkinter.CTkButton(main_frame1,corner_radius=0,height=10,text="Go to the start page",
## command=lambda: controller.show_frame("StartPage"))
## button.grid(row=0,column=0)
## button1 = customtkinter.CTkButton(main_frame1, text="go to page two",
## command=lambda: controller.show_frame("PageTwo"))
## button1.grid(row=0,column=1)
class Pass_det(CTkFrame):
def __init__(self, parent, controller):
CTkFrame.__init__(self, parent)
#For every frame...
self.controller = controller
main_frame1=CTkFrame(master=self)
main_frame1.pack(fill=BOTH, expand=1)
header=CTkFrame(main_frame1,width=925,height=55,corner_radius=0,fg_color="#57a1f8")
header.pack()
man_lab=CTkLabel(header,text="Welcome Manager",bg='white',text_font=('Microsoft YaHei UI Light',23))
man_lab.place(x=10,y=6)
nav_frame=CTkFrame(main_frame1,height=37,width=925,corner_radius=0,fg_color="#1f6aa5")
nav_frame.pack(anchor="w",fill=BOTH,padx=0,pady=0)
but1=CTkButton(nav_frame,text="Bookings",corner_radius=0,height=35,width=90,command=lambda: controller.show_frame("Book_det"))
but1.pack(side=LEFT,pady=0,padx=0)
but2=CTkButton(nav_frame,text="Passengers",fg_color="#144870",corner_radius=0,height=35,width=100,command=lambda: controller.show_frame("Pass_det"))
but2.pack(side=LEFT,pady=0,padx=0)
but3=CTkButton(nav_frame,text='',corner_radius=0,height=35,width=1000,state=DISABLED)
but3.pack(side=LEFT,pady=0,padx=0,fill=BOTH)
fs_frame = CTkFrame(main_frame1)
fs_frame.pack(fill=BOTH,expand=1,pady=25,padx=25)
# fs_frame.pack()
reg_dep = ttk.Treeview(fs_frame,height=22)
CTkLabel(fs_frame,text="").pack()
reg_dep['columns'] = ('Passenger_ID', 'First_Name', 'Last_Name',
'Passport_ID', 'Meal_Preference','Phone_number',
'Email', 'Class')
reg_dep.column("#0", width=0, stretch=NO)
reg_dep.column('Passenger_ID',anchor=CENTER, width=120)
reg_dep.column('First_Name',anchor=CENTER, width=140)
reg_dep.column('Last_Name',anchor=CENTER,width=140)
reg_dep.column('Passport_ID',anchor=CENTER,width=140)
reg_dep.column('Meal_Preference',anchor=CENTER,width=160)
reg_dep.column('Phone_number',anchor=CENTER,width=160)
reg_dep.column('Email',anchor=CENTER,width=140)
reg_dep.column('Class',anchor=CENTER,width=160)
reg_dep.heading("#0",text="",anchor=CENTER)
reg_dep.heading('Passenger_ID',text='Passenger_ID',anchor=CENTER)
reg_dep.heading('First_Name',text='First_Name',anchor=CENTER)
reg_dep.heading('Last_Name',text='Last_Name',anchor=CENTER)
reg_dep.heading('Passport_ID',text='Passport_ID',anchor=CENTER)
reg_dep.heading('Meal_Preference',text='Meal_Preference',anchor=CENTER)
reg_dep.heading('Phone_number',text='Phone_number',anchor=CENTER)
reg_dep.heading('Email',text='Email',anchor=CENTER)
reg_dep.heading('Class',text='Class',anchor=CENTER)
import mysql.connector as mycon
conn=mycon.connect(host="localhost",user="root",passwd="12345678",database="aurora_airlines")
cursor=conn.cursor()
cursor.execute("Select * from passengers;")
data=cursor.fetchall()
Records=[]
for row in data:
Records.append(row)
count=cursor.rowcount
for iid in range(count):
reg_dep.insert(parent='',index='end',iid=iid,text='',
values=(Records[iid][0],Records[iid][1],Records[iid][2],Records[iid][3], Records[iid][4],Records[iid][5],Records[iid][6],Records[iid][7]))
reg_dep.pack(pady=44)
def Display():
root=SampleApp()
root.title("Manager_Login")
root.geometry('925x500+300+200')
root.resizable(False,False)
root.configure(bg="white")
root.mainloop()
I keep getting the 'image "pyimage2" doesn't exist' error. Then when I used the call method, it kept opening another python window which I don't want. I also don't want to merge the above codes into one file since I have a lot of code to add for the other parts of the project.
I apologize for the messy code since these were just test files
I'm just a beginner in python so I might have made some mistakes I'm not aware of. I would be grateful if anyone could help me! Thank you!

Related

How to execute after() method in the second page when it actually gets open using frame in tkinter?

Following is the code that by default shows the StartPage (first Frame) when the app runs, as soon as the user clicks on the button, it redirects to another page i.e., Page1 (second Frame). I want to execute self.after(3000, lambda: (canvas.create_image(50,50,image=self.character1, anchor=NW))) after 3 seconds when the user clicks on the button when the second page (frame) opens. But what I'm getting currently is the after() method executes after 3 seconds but on the initiation of the app. i.e., when the StartPage appears. Please help me to achieve this in my code. I'm new in tkinter! Thanks.
from tkinter import *
from PIL import Image, ImageTk
class tkinterApp(Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
# __init__ function for class Tk
Tk.__init__(self, *args, **kwargs)
# creating a container
container = Frame(self)
container.pack(side = "top", fill = "both", expand = True)
# initializing frames to an empty array
self.frames = {}
# iterating through a tuple consisting
# of the different page layouts
for F in (StartPage, Page1):
frame = F(container, self)
# initializing frame of that object from
# startpage, page1, page2 respectively with
# for loop
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.update() #edited this
self.show_frame(StartPage)
# to display the current frame passed as
# parameter
def show_frame(self, cont): # cont = page_name
if cont not in self.frames:
self.frames[cont] = cont(container, self)
frame = self.frames[cont]
frame.tkraise()
frame.event_generate("<<ShowFrame>>")
# first window frame startpage
class StartPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.bind("<<ShowFrame>>", self.myStartPage)
def myStartPage(self,controller):
super(StartPage).__init__()
print(controller)
canvas = Canvas(self,width=300, height=300, bd=0, highlightthickness=0, relief='ridge')
canvas.pack()
self.background = PhotoImage(file="background.png")
canvas.create_image(300,300,image=self.background, tags="B")
self.character1 = PhotoImage(file="bg-e-butd.png")
obj1 = canvas.create_image(50,50,image=self.character1, anchor=NW)
canvas.tag_bind(obj1, '<1>', lambda event=None : controller.show_frame(Page1))
# second window frame page1
class Page1(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
canvas = Canvas(self,width=300, height=300, bd=0, highlightthickness=0, relief='ridge')
canvas.pack()
self.background = PhotoImage(file="background.png")
canvas.create_image(300,300,image=self.background, tags="B")
self.character1 = PhotoImage(file="bg-e-butd.png")
self.after(1000, lambda: (canvas.create_image(50,50,image=self.character1, anchor=NW)))
# Driver Code
app = tkinterApp()
app.title("Title")
app.mainloop()

Menu item in Tkinter is not working properly (in MacOS)

I am making a tkinter app with multiple pages. The simple version of the codes I used is shown below. I added the menu to the root of the app and gave one option of File with sub-option of "Reload Defaults" and "Exit".
When I run this code then I do get the menu but not on the GUI but the main menu bar of Mac. And the menu is unresponsive. I am not sure what I am doing wrong!
import tkinter as tk
from tkinter import ttk
from tkinter import RAISED
LARGEFONT =("Verdana", 35)
class tkinterApp(tk.Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
# __init__ function for class Tk
tk.Tk.__init__(self, *args, **kwargs)
# creating a container
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
container2 = tk.Frame(self, relief=RAISED, borderwidth=2)
container2.pack(side="bottom",fill="both", expand=True)
container2.grid_rowconfigure(0, weight = 1)
container2.grid_columnconfigure(0, weight = 1)
def runProg():
print("response from runProg")
#get all entry value from page 2
runButton = ttk.Button(container2, text="Run", command=runProg)
runButton.pack(side="left", padx=5, pady=5)
######################################################
## Menu items
progMenu = tk.Menu(self,tearoff=0)
self.config(menu=progMenu)
#create File menu
def reload_command():
pass
fileMenu = tk.Menu(progMenu)
progMenu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Reload Defaults", command=reload_command)
fileMenu.add_command(label="Exit", command=reload_command)
######################################################
# initializing frames to an empty array
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(StartPage)
# to display the current frame passed as
# parameter
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
# first window frame startpage
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# label of frame Layout 2
label = ttk.Label(self, text ="Startpage", font = LARGEFONT)
# putting the grid in its place by using
# grid
label.grid(row = 0, column = 2, padx = 10, pady = 10)
app = tkinterApp()
app.mainloop()
Any help would be greatly appreciated!
You might want to change the menu to be buttons at the top of the grid as on a Mac you will get this bug, but on windows it works perfectly fine.

Frame containing a scrollable canvas is not taking up the rest of the allotted Tk window

I have written an application that allows users to select a directory and load the info in the directory. The user can then select which aspects of the files to display in a figure. The figure is placed in a Tkinter-matplotlib canvas which is within a canvas window that the user can scroll. The issue I am having is that the frame (canvas_frame in StartPage) containing the scrollable frame doesn't take the allotted space in the Tkinter window.
The code below replicates the issue and the the image is what the application looks like. Most of the code for the scrollable frame was taken from ex. 1 and ex. 2. An image of the application is here:
https://imgur.com/ELXmehG
from tkinter import Tk, Frame, Canvas
from tkinter.ttk import Scrollbar
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg as FigCanvas
from matplotlib.figure import Figure
class Scrollable(Frame):
def __init__(self, frame, fig, width=16):
# Base class initialization
Frame.__init__(self, frame)
# Instance variable for tkinter canvas
self.tk_cnv = Canvas(frame, highlightthickness=0)
self.tk_cnv.pack(side='left', fill='both', expand=True)
# Instance variable for the scroll-bar
v_scroll = Scrollbar(frame, width=width)
v_scroll.pack(side="right", fill="y", expand=False)
v_scroll.config(command=self.tk_cnv.yview)
v_scroll.activate(" ")
# Instance variable for the matplotlib canvas
self.mpl_cnv = FigCanvas(fig, frame)
self.cnv_widget = self.mpl_cnv.get_tk_widget()
self.cnv_widget.config(yscrollcommand=v_scroll.set)
self.cnv_widget.bind("<Configure>", self.__fill_canvas)
# Assign frame generated by the class to the canvas
# and create a scrollable window for it.
self.windows_item = \
self.tk_cnv.create_window((0, 900), window=self.cnv_widget, anchor='e',
tag='self.canvas')
self.tk_cnv.config(scrollregion=self.tk_cnv.bbox("all"))
def __fill_canvas(self, event):
# Enlarge the windows item to the canvas width
canvas_width = event.width
canvas_height = event.height
self.tk_cnv.itemconfig(self.windows_item, width=canvas_width,
height=canvas_height)
class StartPage(Frame):
""" Tkinter based class for single frame upon which widgets
such as buttons, check-buttons, and entry are used as a
simple graphical user interface.
"""
LARGE_FONT = ("Veranda", 12)
def __init__(self, parent, controller):
Frame.__init__(self, parent)
# Instance variables with page/window info of current frame
self.window = parent
# Instance variable for third row of widgets
self.canvas_frame = Frame(self.window, relief="sunken")
self.canvas_frame.grid(row=0, column=0, pady=5, sticky="news")
# Instance variables for the figure
self.plot_fig = Figure(figsize=[14.0, 18.0])
# Instance variable for the frame with scrolling functionality
self.canvas_body = Scrollable(self.canvas_frame, self.plot_fig)
self.canvas = self.canvas_body.mpl_cnv
self.canvas_setup()
def canvas_setup(self):
self.canvas_frame.grid_rowconfigure(2, weight=1)
self.canvas_frame.grid_columnconfigure(0, weight=1)
class MainContainer(Tk):
""" Tkinter based class used to generate a single window
and contain a single frame. The frame contains multiple
widgets for user choice and visualization.
"""
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
Tk.wm_title(self, "Sequence Viewer")
Tk.wm_resizable(self, width=True, height=True)
container = Frame(self)
container.grid_configure(row=0, column=0, sticky="nsew")
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
self.show_frame(StartPage)
self.center_window()
def show_frame(self, frame_to_add):
frame = self.frames[frame_to_add]
frame.tkraise()
def center_window(self):
w = 1100
h = 900
sw = self.winfo_screenwidth()
sh = self.winfo_screenheight()
x = (sw - w) / 2
y = (sh - h) / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
if __name__ == "__main__":
app = MainContainer()
app.mainloop()
The major cause of the issue was the use of the initial Frame object from the MainContainer class to instantiate the Frame in which the Scrollable class is contained. The object of the MainContainer is what should have been passed, this is because it inherits from the Tk class.
Secondly, the mixture of window managers was causing problems. Because of this I switched to pack exclusively. The solution is below.
from tkinter import Tk, Frame, Canvas
from tkinter.ttk import Scrollbar
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg as FigCanvas
from matplotlib.figure import Figure
class Scrollable(Frame):
def __init__(self, frame, fig, width=16):
# Base class initialization
Frame.__init__(self, frame)
# Instance variable for tkinter canvas
self.tk_cnv = Canvas(frame, highlightthickness=0)
self.tk_cnv.pack(side="left", anchor="nw", fill="both",
expand=True)
# Instance variable for the scroll-bar
v_scroll = Scrollbar(frame)
v_scroll.pack(side="right", fill="y", expand=False)
v_scroll.config(command=self.tk_cnv.yview, width=width)
v_scroll.activate("slider")
# Instance variable for the matplotlib canvas
self.mpl_cnv = FigCanvas(fig, frame)
self.cnv_widget = self.mpl_cnv.get_tk_widget()
self.tk_cnv.config(yscrollcommand=v_scroll.set)
self.tk_cnv.bind("<Configure>", self.__fill_canvas)
# Assign frame generated by the class to the canvas
# and create a scrollable window for it.
self.windows_item = \
self.tk_cnv.create_window((0, 900), window=self.cnv_widget, anchor='e',
tag='self.canvas')
self.tk_cnv.config(scrollregion=self.tk_cnv.bbox("all"))
def __fill_canvas(self, event):
# Enlarge the windows item to the canvas width
canvas_width = event.width
canvas_height = event.height * 2.825
self.tk_cnv.itemconfig(self.windows_item, width=canvas_width,
height=canvas_height)
class StartPage(Frame):
""" Tkinter based class for single frame upon which widgets
such as buttons, check-buttons, and entry are used as a
simple graphical user interface.
"""
LARGE_FONT = ("Veranda", 12)
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
# Instance variable for third row of widgets
self.canvas_frame = Frame(self.controller, relief="sunken")
self.canvas_frame.pack(side="top", anchor="nw", fill="both",
expand=True)
# Instance variables for the figure
self.plot_fig = Figure(figsize=[14.0, 18.0])
# Instance variable for the frame with scrolling functionality
self.canvas_body = Scrollable(self.canvas_frame, self.plot_fig)
self.canvas = self.canvas_body.mpl_cnv
# Instance variable for third row of widgets
self.control_frame = Frame(self.controller, relief="sunken")
self.control_frame.pack(side="right", anchor="ne", fill="y",
expand=True)
class MainContainer(Tk):
""" Tkinter based class used to generate a single window
and contain a single frame. The frame contains multiple
widgets for user choice and visualization.
"""
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
Tk.wm_title(self, "Sequence Viewer")
Tk.wm_resizable(self, width=True, height=True)
container = Frame(self)
container.pack_configure(side="top", anchor="nw", fill="both")
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
self.show_frame(StartPage)
self.center_window()
def show_frame(self, frame_to_add):
frame = self.frames[frame_to_add]
frame.tkraise()
def center_window(self):
w = 1100
h = 900
sw = self.winfo_screenwidth()
sh = self.winfo_screenheight()
x = (sw - w) / 2
y = (sh - h) / 2
self.geometry('%dx%d+%d+%d' % (w, h, x, y))
if __name__ == "__main__":
app = MainContainer()
app.mainloop()

Python Tkinter Edit Menu Window

I'm trying to edit Menu window. How can i edit it?
This is for Windows.
from tkinter import *
Window = Tk()
MB = Menu(Window)
Window.config(menu=MB)
Menubar = Menu(MB)
MB.add_cascade(label="File", menu=Menubar)
Menubar.add_command(label="New File")
#Btn1 = Button(Menubar, width=20, text="Button").pack() #I failed.
Window.mainloop()
I tried Btn1 = Button(Menubar, width=20, text="Button").pack()
But this one couldn't work.
usually you add items to menu like this - but what are looking for?
window = Tk()
mb = Menu(window)
menu_bar = Menu(mb, tearoff=0)
menu_bar.add_command(label="New")
menu_bar.add_command(label="Open")
menu_bar.add_command(label="Save")
menu_bar.add_command(label="Save as...")
menu_bar.add_command(label="Close")
menu_bar.add_separator()
menu_bar.add_command(label="Exit", command=window.quit)
mb.add_cascade(label="File", menu=menu_bar)
top.config(menu=mb)
You cannot add arbitrary widgets to a menu. To add items to a menu you must use one of the following functions available on the Menu object:
add
add_command
add_cascade
add_checkbutton
add_radiobutton
add_separator
To add a textual label you can use add_command and set the command attribute to None.
All of these are documented with the Menu widget definition itself, and on just about any site that includes widget documentation.
If you're looking for a control of Menu Bar with Buttons you can do it. All of the code will be in the same file.py .Libraries in Python3 (For Python 2 change to import Tkinter as tk). Later you can redirect to each window with each menu with buttons.
import tkinter as tk
from tkinter import ttk
Global list of titles for
nombre_ventanas={'PageOne'}
One menubar, you need to add similar for each menu that you want to display. menubar_global, menubar1, menubar2, ...
def menubar_global(self, root, controller):
menubar_global = tk.Menu(root)
page_1 = tk.Menu(menubar_global, tearoff=0)
# With Submenu for page_1
page_1_1=tk.Menu(page_1 , tearoff=0)
page_1_2=tk.Menu(page_1 , tearoff=0)
Main
if __name__ == "__main__":
app = ControlWindow()
app.mainloop()
Class for windows control
class ControlWindow(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 = {}
self._nombre_ventanas = nombre_ventanas
for F in self._nombre_ventanas:
F = eval(F)
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
# First window
self.show_frame(Login)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
# Title for each page
self.title(titulo_ventanas[cont._name_for_menu_bar])
# Here you can add if-sentece for each menubar that you want
if cont._name_for_menu_bar != "PageOne":
# Menu bar
print("show_frame", cont)
menubar = frame.menubar(self)
self.configure(menu=menubar)
else:
menubar = 0
self.configure(menu=menubar)
class Ventana_proveedores(tk.Frame):
_name_for_menu_bar = "Ventana_proveedores"
_config = configuracion
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Button(self, text='Regresar', font=FONT_LABELFRAME,
command=lambda: controller.show_frame(Ventana_gerente)).grid(row=0, column=0)
def menubar(self, root):
return menubar_global(self, root, self.controller)
Later Each Page need to have this configuration
class PageOne(tk.Frame):
_name_for_menu_bar = "PageOne"
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
def menubar(self, root):
return menubar_global(self, root, self.controller)

Pythonic way to add user defined image into tkinter frame

I am attempting to having a frame display an image that's opened through filedialog. My current method initializes the frame in Step1 with "image1path", and then I'd like to update it to some "image2path" specified by the user. I am attempting to do this through the Data.currentJPEG attribute.
Is there a better way that involves not initializing with a "dummy" image?
If this is the correct way, why do my commented out lines at the bottom return: " 'str' object has no attribute '_bind' " when Step1 is not a string. I thought Step1 was what allowed self.bind to work on the startPage. Is this not the correct method of updating the image in the frame?
Bonus side question: if I change weight=100 to weight=1 in the start page lines, why does the open .jpg button's location scale at all?
This code structure can be found here
Resizing an image this way can be found here
The method I attempt to use follows this answer, where a new function is called when the button is pressed that updates the image. However, I believe I am running into issues because my image uses the resizing function as well.
import os
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import filedialog
image1path='mainGraphic.jpg'
cwd = os.getcwd()
# where opened file data with be stored
class Data():
# this sets initial values for the class attributes
def __init__(self):
self.currentJPEG=image1path
class program(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.title('program name')
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# frames are laid ontop of each other, startPage shown first
self.frames = {}
for Frame in (StartPage, Step1):
frame = Frame(container, self)
self.frames[Frame] = frame
frame.grid(row = 0, column = 0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
self.show_frame(StartPage)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
# scale rows and columns (make button scaling negligible)
self.rowconfigure(0,weight=0)
self.rowconfigure(1,weight=100) #bonus question refers to these 2 lines
self.columnconfigure(0,weight=100)
# button to open an image in Step 1,
# must pass program so app.showframe is available,
# must pass Step1 so the image attributes are available?
button = tk.Button(self, text='Open .jpg File in new frame',
command=lambda: Step1.openJPEG(program))
button.grid(row=0, column=0, sticky='ew')
# add the main graphic
self.canvas = tk.Canvas(self,bg='black')
self.canvas.grid(row=1, column=0, sticky='nsew')
self.img_copy = Image.open(image1path)
self.image = None #this is overriden every time the image is redrawn so there is no need to make it yet
self.bind("<Configure>",self.resizeImage)
def resizeImage(self,event):
origin = (0,0)
size = (event.width, event.height)
if self.bbox("bg") != origin + size:
self.canvas.delete("bg")
self.image = self.img_copy.resize(size)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
self.canvas.tag_lower("bg","all")
class Step1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# give even weight to each subframe
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=100)
self.columnconfigure(1, weight=100)
# Frame1, this is on the left and empty
frame1 = tk.Frame(self, bg="grey")
frame1.grid(row=0, column=0, sticky='nsew')
# Frame2, this is where image preview is
frame2 = tk.Frame(self, bg="grey")
frame2.grid(row=0, column=1, sticky='nsew')
# scale rows and columns with equal weight
frame2.rowconfigure(0,weight=1)
frame2.columnconfigure(0,weight=100)
frame2.columnconfigure(1,weight=100)
# initialize where image preview will be in frame2
self.canvas = tk.Canvas(frame2,bg='black')
self.canvas.grid(row=0, column=1, sticky='nsew')
self.img_copy = Image.open(Data.currentJPEG)
self.image = None
self.bind("<Configure>",self.resizeImage)
def resizeImage(self,event):
origin = (0,0)
size = (event.width, event.height) # these need to get height/width of their frame, not Step1
if self.bbox("bg") != origin + size:
self.canvas.delete("bg")
self.image = self.img_copy.resize(size)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
self.canvas.tag_lower("bg","all")
# update the image in frame2 using opened jpeg image
def openJPEG(program):
filePath = filedialog.askopenfilename(initialdir=cwd,
filetypes=(("JPEG",".jpg"),("All Files","*.*")),
title="Open JPEG")
try:
with open(filePath) as image: #***need a better 'try' statement for only jpeg is opened'
app.show_frame(Step1)
except:
print('could not open image')
return
## update image preview from mainGraphic to opened JPEG; these lines aren't working
Data.currentJPEG=filePath
#Step1.img_copy = Image.open(Data.currentJPEG)
#Step1.image = None
#Step1.bind("<Configure>",Step1.resizeImage)
# initalize data class
Data=Data()
# run program
app = program()
If all you want to do is to let your user manually select a file, and then have your tkinter GUI display it, you just need a Button and a Canvas.
Code:
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.image as mpimg
from tkinter import filedialog
import tkinter as tk
import os
class program(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# Create a button to load a jpg
self.button = tk.Button(self, text="Load image", command=self.openJPEG)
self.button.pack()
# Create a canvas on which to show the jpg
self.frame = tk.Frame(self)
self.frame.pack(fill=tk.BOTH, expand=1)
self.create_canvas()
def openJPEG(self):
# Display a dialog for the user to select a jpg file,
filePath = filedialog.askopenfilename(initialdir=os.getcwd(),
filetypes=(("JPEG",".jpg"),
("All Files","*.*")),
title="Open JPEG")
# Show the selected jpg on the canvas
img = mpimg.imread(filePath)
self.ax1.imshow(img)
self.canvas1.draw()
def create_canvas(self):
""" Add a canvas to plot images """
self.fig1 = Figure(frameon=False, figsize=(6, 4.5))
self.canvas1 = FigureCanvasTkAgg(self.fig1, master=self.frame)
self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=1)
self.ax1 = self.fig1.add_axes([0, 0, 1, 1])
self.ax1.axis('off')
# Run program
app = program()
app.mainloop()
If you want to keep your multiple classes structure, you will have to make better use of the root part of your GUI (called controller in your subframes) to communicate between the different frames. See the code below to get you started:
import os
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import filedialog
# where opened file data with be stored
class Data():
# this sets initial values for the class attributes
def __init__(self):
self.currentJPEG=""
class program(tk.Tk):
def __init__(self, Data):
tk.Tk.__init__(self)
self.Data = Data
container = tk.Frame(self)
container.pack(fill="both", expand=True)
# frames are laid ontop of each other, startPage shown first
self.frames = {}
for Frame in (StartPage, Step1):
frame = Frame(container, self)
self.frames[Frame] = 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):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# button to open an image in Step 1,
button = tk.Button(self, text='Open .jpg File in new frame',
command= self.openJPEG)
button.grid(row=0, column=0, sticky='ew')
# add empty canvas
self.canvas = tk.Canvas(self,bg='black')
self.canvas.grid(row=1, column=0, sticky='nsew')
def openJPEG(self):
self.openJPEG
filePath = filedialog.askopenfilename(initialdir=os.getcwd(),
filetypes=(("JPEG",".jpg"),
("All Files","*.*")),
title="Open JPEG")
# Update the image in Step1 frame
self.controller.Data.currentJPEG = filePath
self.controller.frames[Step1].show_current_image()
# Show Step1 frame
self.controller.show_frame(Step1)
class Step1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# Frame2, this is where image preview is
frame2 = tk.Frame(self, bg="grey")
frame2.grid(row=0, column=1, sticky='nsew')
# initialize where image preview will be in frame2
self.canvas = tk.Canvas(frame2,bg='black')
self.canvas.grid(row=0, column=1, sticky='nsew')
def show_current_image(self):
self.image = Image.open(self.controller.Data.currentJPEG)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor="nw", image=self.background_image,
tags="bg")
# initalize data class
Data = Data()
# run program
app = program(Data)
app.mainloop()

Categories