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!
I started building a Tkinter application and was initially using matplotlib's Figure and figure.add_subplot. With that everything works perfectly. For more customization, I now want to move to pyplot and subplot2grid, but in doing so, suddenly all of my tkinter variable stop working.
In my MWE, the variable gArrChoice tracks which radio button is selected and should default to the first option. Based on this option, the graph should plot a line hovering around 0.1. If the second option gets selected, the graph should change to hover around 5. The graph auto-updates ever 2.5 seconds. If you comment out the 3 lines below "Working" and use the 3 "Not Working" lines instead, the default settings of the variable stops working and switching between radio buttons has no effect anymore. Declaring a inside the animate function does not change the problem.
How can I use plt with Tkinter and not destroy my variables?
MWE:
import tkinter as tk
import matplotlib
matplotlib.use("TkAgg") #make sure you use the tkinter backend
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.animation as animation
import numpy as np
gArrChoice = 0
#Working - using Figure and add_subplot
from matplotlib.figure import Figure
f = Figure()
a = f.add_subplot(121)
#Not Working - using plt and subplot2grid
# from matplotlib import pyplot as plt
# f = plt.figure()
# a = plt.subplot2grid((10, 7), (0, 0), rowspan=10, colspan=5)
class BatSimGUI(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)
self.frames = {}
frame = StartPage(container,self)
self.frames[StartPage] = frame
frame.grid(row=0, column=0, sticky="nsew")
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#Set defaults for global variable
global gArrChoice
gArrChoice = tk.IntVar()
gArrChoice.set(1)
radioArr1 = tk.Radiobutton(self, variable=gArrChoice, text="Exponential", value=1, command= lambda: print(gArrChoice.get()))
radioArr1.grid(row=2, column=0)
radioArr2 = tk.Radiobutton(self, variable=gArrChoice, text="Normal", value=2, command= lambda: print(gArrChoice.get()))
radioArr2.grid(row=3, column=0)
#Add Canvas
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().grid(row=1, column=1, columnspan=7, rowspan = 10)
def animate(i):
global gArrChoice
if gArrChoice.get() == 1:
lam = np.random.exponential(scale=.1, size = 100).reshape(-1,1)
else:
lam = np.random.normal(loc=5, scale=1, size = 100).reshape(-1,1)
a.clear()
a.step(list(range(100)), list(lam))
#Actually run the interface
app = BatSimGUI()
app.geometry("800x600")
ani = animation.FuncAnimation(f, animate, interval = 2500)
app.mainloop()
I'think that an OO approach it'would be better.
See below, I've use thread and queue to manage the plot animation, you can even set time interval and change on fly the graph type
Good job anyway, very interesting
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import threading
import queue
import time
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
try:
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk as nav_tool
except:
from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg as nav_tool
import numpy as np
class MyThread(threading.Thread):
def __init__(self, queue, which, ops, interval):
threading.Thread.__init__(self)
self.queue = queue
self.check = True
self.which = which
self.ops = ops
self.interval = interval
def stop(self):
self.check = False
def run(self):
while self.check:
if self.which.get() ==0:
lam = np.random.exponential(scale=.1, size = 100).reshape(-1,1)
else:
lam = np.random.normal(loc=5, scale=1, size = 100).reshape(-1,1)
time.sleep(self.interval.get())
args = (lam, self.ops[self.which.get()])
self.queue.put(args)
else:
args = (None, "I'm stopped")
self.queue.put(args)
class Main(ttk.Frame):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.which = tk.IntVar()
self.interval = tk.DoubleVar()
self.queue = queue.Queue()
self.my_thread = None
self.init_ui()
def init_ui(self):
f = ttk.Frame()
#create graph!
self.fig = Figure()
self.fig.suptitle("Hello Matplotlib", fontsize=16)
self.a = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, f)
toolbar = nav_tool(self.canvas, f)
toolbar.update()
self.canvas._tkcanvas.pack(fill=tk.BOTH, expand=1)
w = ttk.Frame()
ttk.Button(w, text="Animate", command=self.launch_thread).pack()
ttk.Button(w, text="Stop", command=self.stop_thread).pack()
ttk.Button(w, text="Close", command=self.on_close).pack()
self.ops = ('Exponential','Normal',)
self.get_radio_buttons(w,'Choice', self.ops, self.which,self.on_choice_plot).pack(side=tk.TOP, fill=tk.Y, expand=0)
ttk.Label(w, text = "Interval").pack()
tk.Spinbox(w,
bg='white',
from_=1.0, to=5.0,increment=0.5,
justify=tk.CENTER,
width=8,
wrap=False,
insertwidth=1,
textvariable=self.interval).pack(anchor=tk.CENTER)
w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
f.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
def launch_thread(self):
self.on_choice_plot()
def stop_thread(self):
if self.my_thread is not None:
if(threading.active_count()!=0):
self.my_thread.stop()
def on_choice_plot(self, evt=None):
if self.my_thread is not None:
if (threading.active_count()!=0):
self.my_thread.stop()
self.my_thread = MyThread(self.queue,self.which, self.ops, self.interval)
self.my_thread.start()
self.periodiccall()
def periodiccall(self):
self.checkqueue()
if self.my_thread.is_alive():
self.after(1, self.periodiccall)
else:
pass
def checkqueue(self):
while self.queue.qsize():
try:
args = self.queue.get()
self.a.clear()
self.a.grid(True)
if args[0] is not None:
self.a.step(list(range(100)), list(args[0]))
self.a.set_title(args[1], weight='bold',loc='left')
else:
self.a.set_title(args[1], weight='bold',loc='left')
self.canvas.draw()
except queue.Empty:
pass
def get_radio_buttons(self, container, text, ops, v, callback=None):
w = ttk.LabelFrame(container, text=text,)
for index, text in enumerate(ops):
ttk.Radiobutton(w,
text=text,
variable=v,
command=callback,
value=index,).pack(anchor=tk.W)
return w
def on_close(self):
if self.my_thread is not None:
if(threading.active_count()!=0):
self.my_thread.stop()
self.parent.on_exit()
class App(tk.Tk):
"""Start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_exit)
self.set_title()
self.set_style()
Main(self)
def set_style(self):
self.style = ttk.Style()
#('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
self.style.theme_use("clam")
def set_title(self):
s = "{0}".format('Simple App')
self.title(s)
def on_exit(self):
"""Close all"""
if messagebox.askokcancel("Simple App", "Do you want to quit?", parent=self):
self.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()
There seems to be a bug on updating the IntVar() when you use pyplot instead. But you can workaround it if you force a change in value in your radio buttons:
radioArr1 = tk.Radiobutton(self, variable=gArrChoice, text="Exponential", value=1, command= lambda: gArrChoice.set(1))
radioArr2 = tk.Radiobutton(self, variable=gArrChoice, text="Normal", value=2, command= lambda: gArrChoice.set(2))
Or you can make your IntVar as an attribute of StartPage instead which seems to work just fine.
import tkinter as tk
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.animation as animation
import numpy as np
from matplotlib import pyplot as plt
class BatSimGUI(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)
self.frames = {}
self.start_page = StartPage(container,self)
self.frames[StartPage] = self.start_page
self.start_page.grid(row=0, column=0, sticky="nsew")
self.start_page.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.gArrChoice = tk.IntVar()
self.gArrChoice.set(1)
radioArr1 = tk.Radiobutton(self, variable=self.gArrChoice, text="Exponential", value=1)
radioArr1.grid(row=2, column=0)
radioArr2 = tk.Radiobutton(self, variable=self.gArrChoice, text="Normal", value=2)
radioArr2.grid(row=3, column=0)
self.f = plt.figure()
self.a = plt.subplot2grid((10, 7), (0, 0), rowspan=10, colspan=5)
canvas = FigureCanvasTkAgg(self.f, self)
canvas.draw()
canvas.get_tk_widget().grid(row=1, column=1, columnspan=7, rowspan = 10)
def animate(self,i):
if self.gArrChoice.get() == 1:
lam = np.random.exponential(scale=.1, size = 100).reshape(-1,1)
else:
lam = np.random.normal(loc=5, scale=1, size = 100).reshape(-1,1)
self.a.clear()
self.a.step(list(range(100)), list(lam))
app = BatSimGUI()
app.geometry("800x600")
ani = animation.FuncAnimation(app.start_page.f, app.start_page.animate, interval=1000)
app.mainloop()
It seems the problem is to replace
# Not Working - using plt and subplot2grid
from matplotlib import pyplot as plt
f = plt.figure()
a = plt.subplot2grid((10, 7), (0, 0), rowspan=10, colspan=5)
in a pyplot- independent fashion. One option is the use of gridspec:
from matplotlib.figure import Figure
f = Figure()
gs = f.add_gridspec(10,7)
a = f.add_subplot(gs[:, :5])