Pythonic way to add user defined image into tkinter frame - python

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

Related

How to link two classes from two different python files

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!

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 GUI to scroll through photos in a window

I am trying to develop a Python Tkinter widget that opens a window displaying a photo and allows the user to scroll through the photos using a scroll bar. For context, the idea is to be able to scroll through a timer-series of photographs.
So far I've been able to make a Tkinter canvas displaying an image, and a Tkinter "Scale" slider, but I am having trouble combining them to meet my goal. The result of the below code is an empty canvas window and a separate slider. The slider works and prints its position when moved, but no photo ever loads. I was hoping that when the bar was moved to position 3, photo 3 would load.
Any idea what I'm missing?
import Tkinter as tk
from PIL import ImageTk, Image
from Tkinter import *
class ImageCanvas(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = Canvas(self, width=720, height=480, bd=0)
self.canvas.grid(row=0, column=0, sticky='nsew', padx=4, pady=4)
self.root = tk.Tk()
self._job = NONE
self.slider = tk.Scale(self.root, from_=0, to=3, orient = "horizontal", command=self.updateValue)
self.slider.pack()
self.root.mainloop()
def updateValue(self, event):
if self._job:
self.root.after_cancel(self._job)
self._job = self.root.after(500, self.result)
def result(self):
self._job=None
print self.slider.get()
returnedValue = self.slider.get()
class ImgTk(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.main = ImageCanvas(self)
self.main.grid(row=0, column=0, sticky='nsew')
self.c = self.main.canvas
self.currentImage = {}
self.load_imgfile(images[ImageCanvas.returnedValue()])
def load_imgfile(self, filename):
self.img = Image.open(filename)
self.currentImage['data'] = self.img
self.photo = ImageTk.PhotoImage(self.img)
self.c.xview_moveto(0)
self.c.yview_moveto(0)
self.c.create_image(0, 0, image=self.photo, anchor='nw', tags='img')
self.c.config(scrollregion=self.c.bbox('all'))
self.currentImage['photo'] = self.photo
images = ['/Users/Evan/Documents/Temp/4744.png', '/Users/Evan/Documents/Temp/4750.png', '/Users/Evan/Documents/Temp/4757.png']
app = ImgTk()
A couple suggestions may get you on the right track. Move the self.root.mainloop() out of the ImageCanvas class and put it at the end, after app = ImgTk(), as simply mainloop(), so it only get's called ones per instance of your app.
Also, ImageCanvas class doesn't have a method called returnedValue, and the result method doesn't return any value. So, add return returnedValue to the result method. Then ImageCanvas.returnedValue() would need to be ImageCanvas.result(), or you could just say self.main.result().
After making these changes, the first image displays, more work will need to be done to get the other images to load.

Categories