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()