I have a program that receives sensor data through the serial port of my laptop and then prints these values to a screen with a Tkinter gui and adds these values to an array for my matplotlib live graphs. The program works fine for a while but once it gets to the .pop(0) section, I get this error:
ValueError: x and y must have same first dimension, have shapes (5000,) and (5001,)
and no graph data shows when I click my Tkinter button.
I have changed this section if(cntB2>10000): to if(cntB2=>10000): but still no luck.
This is a stripped down version of my script. This will not work if you run it as all the Tkinter labels and placement take a lot of codeing and make it difficult to analyse the problem.
import matplotlib
# Main Tkinter application
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
root.title( "Stylibleue Dashboard")
root.state('zoomed')
root.configure(background='black')
self.grid(row=0, column=0, sticky="nsew") # Thus makes an invisible grid to make the layout
self.grid_rowconfigure(0, weight=3)
self.grid_columnconfigure(0, weight=3)
self.columnconfigure(1, weight=3)
def createWidgets(self):
#B1 Labels --------------------------
self.temperature = Label(self, text="Bassin 1", font=('Verdana', 15), fg="red", bg="black").grid(row=3, column=0, sticky="nsew")
################ This is the Graph page when button is clicked
def button_press2(self):
clicked = True
print (clicked)
drawnow(self.makeFig2) #Call drawnow to update our live graph
plt.pause(.000001) #Pause Briefly. Important to keep drawnow from crashing
def makeFig2(self):
mng = plt.get_current_fig_manager()
mng.window.state('zoomed')
plt.title("D.O graph bassin 2") #Plot the title
plt.grid(True) #Turn the grid on
plt.setp(plt.xticks()[1], rotation=30, ha='right') #ha is the same as horizontalalignment
plt.ylabel('D.O') #Set ylabels
plt.plot(dt2,Oxy2, label='D.O') #plot the temperature
plt.legend(loc='upper left') #plot the legend
plt.draw()
########## This takes the sensor reading
def measure(self):
if com_port_connected == True:
try:
# If there is incoming data to parse and display it
if(arduinoData.inWaiting()>0 ): #and arduinoData.inWaiting()>50 ):
arduinoString = arduinoData.readline()
self.B10.set("")
arduinoString =str(arduinoString) #removes the surrounding rubbish
aaa = arduinoString.split(',')
a = sys.getsizeof(arduinoString)
print("-------Received Sensor data-------")
print(a)
self.B10.set("")
arduinoString =str(arduinoString) #removes the surrounding rubbish
aaa = arduinoString.split(',')
print(arduinoString.split(','))
a = sys.getsizeof(arduinoString)
#################### This updates the GUI labels and adds to the graph array
if aaa[1] == "B2" and Preceed == True:#BASSIN TWO ADDRESS HERE
self.B2.set(str(aaa[3]))
self.B22.set(str(aaa[5]))
self.B22222.set(str(datetime.datetime.now().strftime("%d/%m %H:%M")))
print(datetime.datetime.now().strftime("%d/%m %H:%M"))#%Y-%m-%d %H:%M:%S
try:
tempF2.append(float(aaa[5]))
Oxy2.append(float(aaa[3]))
dt2.append(datetime.datetime.now())
global cntB2
cntB2=cntB2+1
print("cntB2")
print(cntB2)
if(cntB2>10000):
tempF2.pop(0)
Oxy2.pop(0)
dt2.pop(0)
except:
print("Error could not append sensor data")
except:
print("No data received")
self.B10.set("Connect RX")
self.after(1000,self.measure) # Wait 1 second between each measurement
self.after(1000,self.check_buttons) # check for button press
arduinoData.flushOutput()
arduinoData.flushInput()
# Create and run the GUI
root = Tk()
app = Application(master=root)
app.mainloop()
Related
Can somebody help me out with threading in python and getting a progress bar working?
Even research gives quite a lot results, i cannot get it working.
I never did threading before and i cannot tell where to put things correctly.
For testing purposes i prepared a simple GUI with a button and a progress bar:
After clicking the button a simple 3d plot will pop-up.
Such plotting may take some computation time and while a user need to wait, id like to have the GUI not frozen and the progressbar animated.
At the moment the GUI freezes until the plot will show up. And after that the progress bar start the animation.
I have read a lot about threading and to put calculations and gui to different threads?
But im just to noobish to get it working.
Is somebody able to explain me more, direct me to similar problems or documentations?
Or maybe, in case is quickly solved, overtake the simple code and correct it the way it should be?
Thanks in advance for any kind of help.
Python script so far:
from time import sleep
from tkinter import EW
import ttkbootstrap as ttk
import numpy as np
import matplotlib.pyplot as plt
def main():
def plot_sample():
sleep(5) # simulate calculation times
x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(x, y, z,cmap='viridis', edgecolor='none')
ax.set_title('Surface plot')
plt.show()
def progressbar_start():
progressbar.grid(row=1, column=0, sticky=EW, padx=10, pady=10) # let progressbar appear in GUI
progressbar.start(interval=10)
def progressbar_stop():
progressbar.stop()
progressbar.grid_forget() # hide progressbar when not needed
def button_clicked():
progressbar_start() # start progressbar before computation begins
plot_sample() # plotting
progressbar_stop() # stop progressbar after plot is done
# GUI
# window size and settings
root = ttk.Window()
# Basic settings for the main window
root.title('Test progressbar')
root.minsize(300, 200)
root.resizable(True, True)
root.configure(bg='white')
# grid settings for the main window in which LabelFrames are sitting in
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
# Button fto show 3d-plot
button_calc_3dplot = ttk.Button(root, text='Calculate 3D Plot', command=button_clicked)
button_calc_3dplot.grid(row=0, column=0, padx=5, pady=5)
progressbar = ttk.Progressbar(style='success-striped', mode='indeterminate')
# end of GUI
root.mainloop()
if __name__ == "__main__":
main()
I have one solution. The main problem is, that You can't run the plt.show() function in a Thread. From this follows, that you can't run the window and the plt.show function at the same time.
from time import sleep
from tkinter import EW
import ttkbootstrap as ttk
import numpy as np
import matplotlib.pyplot as plt
from threading import Thread
x, y, z = None, None, None
def main():
def calculate_xyz():
sleep(5) # simulate calculation times
global x, y, z
x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)
def progressbar_start():
progressbar.grid(row=1, column=0, sticky=EW, padx=10, pady=10) # let progressbar appear in GUI
progressbar.start(interval=10)
def progressbar_stop():
progressbar.stop()
progressbar.grid_forget() # hide progressbar when not needed
def button_clicked():
progressbar_start() # start progressbar before computation begins
calculate_xyz_thread = Thread(target=calculate_xyz)
calculate_xyz_thread.start() # calculate x, y and z
root.after(500, wait_for_plotting) # wait for plotting and stop animation after finishing
def wait_for_plotting():
if x is None or y is None or z is None:
root.after(500, wait_for_plotting) # run self again
return # wait for calculation
# calculation is finished
progressbar_stop() # stop progressbar "after" plot is done
ax = plt.axes(projection='3d')
ax.plot_surface(x, y, z, cmap='viridis', edgecolor='none')
ax.set_title('Surface plot')
root.after(500, plot_3d)
def plot_3d():
plt.show()
# GUI
# window size and settings
root = ttk.Window()
# Basic settings for the main window
root.title('Test progressbar')
root.minsize(300, 200)
root.resizable(True, True)
root.configure(bg='white')
# grid settings for the main window in which LabelFrames are sitting in
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
# Button fto show 3d-plot
button_calc_3dplot = ttk.Button(root, text='Calculate 3D Plot', command=button_clicked)
button_calc_3dplot.grid(row=0, column=0, padx=5, pady=5)
progressbar = ttk.Progressbar(style='success-striped', mode='indeterminate')
# end of GUI
root.mainloop()
if __name__ == "__main__":
main()
I am using Python with TKinter as GUI; and Matplotlib's FuncAnimation, to display 2 graphs next to each other. These graphs are representing sensor readings (temperature, humidity), and I would like to label both the x-axis and y-axis. (The matplotlib graph title is not required, but I am including it for testing purposes)
I'll try not to divulge unnecessary details; but in simple terms, I have 2 classes representing the sensors, "temperature" and "humidity", and another class "main_window" to combine both the classes into the Tkinter GUI.
This is a preview of the main.py file; including the main_window class.
class main_window(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.wm_title("Indoor Monitoring System")
frame1 = tk.Frame(self)
frame1.grid(column=0, row=0)
frame2 = tk.Frame(self)
frame2.grid(column=1, row=0)
temperature(frame1, self)
humidity(frame2, self)
if __name__ == "__main__":
runObj = main_window()
runObj.mainloop()
and this is a preview of the temperature class
class temperature(tk.Frame):
def __init__(self, parent, controller):
pd.set_option('display.float_format', lambda x: '%.2f' % x)
plt.style.use('fivethirtyeight')
self.x_values = []
self.y_values = []
self.counter = 0
self.fig = plt.figure(figsize=(8, 4), dpi=100)
self.ax1 = self.fig.add_subplot(111)
self.ax1.set(xlabel="Reading Counter", ylabel="Degrees Celcius")
label = tk.Label(parent, text="Temperature Graph", font=("Arial", 12)).grid(column=0, row=0)
canvas = FigureCanvasTkAgg(self.fig, master=parent)
canvas.get_tk_widget().grid(column=0, row=1)
self.ani1 = FuncAnimation(self.fig, self.animate, interval=10000, blit=False)
def animate(self, i):
df = pd.read_csv('C:\\log.csv')
x_temporary_values = df["Counter"]
y_temp_values = df["Temp"]
currrow = x_temporary_values[self.counter]
if currrow is not None:
self.x_values.append(currrow)
self.y_values.append(y_temp_values[self.counter])
self.ax1.plot(self.x_values, self.y_values)
# self.ax1.set(xlabel="Reading Counter", ylabel="Degrees Celcius")
self.counter += 1
The humidity class is very similar.
I am trying to set the xlabel and ylabel as such:
self.ax1.set(xlabel="Reading Counter", ylabel="Degrees Celcius", title="Temperature")
I've also tried:
self.ax1.set_title("Temperature")
self.ax1.set_xlabel("Reading Counter")
self.ax1.set_ylabel("Degrees Celcius")
The title and y_label are initially displayed. After refreshing the graph via the "animate" funxction, the title is retained, the y_label is not. The x_label is never shown.
I have also tried to re-call the self.ax1.set() in the animation function. Does not make a difference.
What am I doing wrong?
Note: that this setup is the only one that worked for me, in the context of trying to animate the graphs. Most other setups that I was more accustomed to, do not work with FuncAnimation.
Also, note that the UI is not refined by any means (especially font sizes). I am concerned with fixing the label issues first.
I've tried using Tk to make a function that will allow users to look at a graph and select if points are wrong. I had this working before, but now my code is hanging every time I run it and try to go to the next graph. Specifically when I click "next graph" and it should run
def _quit(self):
self.master.destroy() # stops mainloop
When I manually stop the code I get this message:
File "C:\Users\laura\Anaconda3\lib\tkinter\__init__.py", line 1429, in mainloop
self.tk.mainloop(n)
KeyboardInterrupt
Any suggestions? I've read using root.destroy() but I haven't been able to get that to work
Thanks!
def config_plot():
tk, ax = plt.subplots()
ax.set(title='Are the peaks okay?')
return (tk, ax)
class matplotlibSwitchGraphs:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.frame.pack(expand=YES, fill=BOTH)
self.fig = Figure(figsize=(12,7))
self.ax = self.fig.gca()
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.graphIndex = 0
self.draw_graph_one()
def config_window(self):
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
print('connect')
self.canvas.mpl_connect("button_press_event", self.on_button_press)
self.button = Button(self.master, text="YES, next graph", command=self._quit) #this is where it gets stuck!
self.button.pack(side=BOTTOM)
self.button_switch = Button(self.master, text="NO", command=self.switch_graphs)
self.button_switch.pack(side=BOTTOM)
def draw_graph_one(self):
self.ax.clear() # clear current axes
self.ax.plot(data)
self.ax.plot(peaks,loc_peaks, marker='o', linestyle='none')
# self.ax.set(xlim=(touchdown_cut[-15]-50,toeoff_cut[-5]+50))
self.ax.set(title='Check the data')
self.canvas.draw()
def draw_graph_two(self):
self.ax.clear()
self.ax.plot(data)
self.ax.set(title='Click all the incorrect peaks')
self.ax.plot(peaks,loc_peaks, marker='o', linestyle='none')
self.canvas.draw()
def on_button_press(self, event):
print('xdata, ydata:', event.xdata, event.ydata)
# return (event.xdata)
global ix
ix = event.xdata
global clicks
clicks.append((ix))
array1 = np.asarray(peaks)
idx1 = (np.abs(array1 - event.xdata)).argmin()
global peaks_adj
global loc_peaks_adj
peaks_adj = np.delete(peaks, idx1)
loc_peaks_adj = np.delete(loc_peaks, idx1)
self.canvas.flush_events()
self.ax.clear()
self.ax.plot(data)
self.ax.set(title='Click all the incorrect peaks')
self.ax.plot(peaks_adj,loc_peaks_adj, marker='o', linestyle='none')
self.canvas.draw()
return (clicks)
def _quit(self):
self.master.destroy() # stops mainloop
def switch_graphs(self):
# Need to call the correct draw, whether we're on graph one or two
self.graphIndex = (self.graphIndex + 1 ) % 2
if self.graphIndex == 0:
self.draw_graph_one()
else:
self.draw_graph_two()
def main():
root = Tk()
matplotlibSwitchGraphs(root)
root.mainloop()
if __name__ == '__main__':
main()
Try changing root.destroy() to self.destroy()as you are working with classes. If using function through a button remove the()after command likecommand=self.destroy`.
Also don't use global, use self. to create a class variable if you want to access the variable in multiple function.
As far as for lags, I would recommend you to use update and update_idletasks.
I am currently working to create a tkinter GUI which shows a matplotlib figure with two sliders. The sliders are to be used for selecting a range of data (they are connected to vertical lines on the plot).
The issue I am running into is that when I change the sliders quickly a few times the GUI freezes. I believe this is due to the on_changed() call I am using to make the sliders update. When you move the slider quickly I believe on_changed() is being called multiple times at a faster rate than the program can keep up with, thus causing the freeze.
Is there any way to add a delay to the on_changed() call so it only looks to see if the slider has been changed every given interval of time (ex. 100 ms)?
Below is example code I found which freezes in the way I described.
import tkinter as tk
from tkinter.ttk import Notebook
from tkinter import Canvas
from tkinter import messagebox as msg
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.widgets import Slider, Button, RadioButtons
class LukeOutline(tk.Tk):
def __init__(self):
# Inherit from tk.Tk
super().__init__()
# Title and size of the window
self.title('Luke Outline')
self.geometry('600x400')
# Create the drop down menus
self.menu = tk.Menu(self,bg='lightgrey',fg='black')
self.file_menu = tk.Menu(self.menu,tearoff=0,bg='lightgrey',fg='black')
self.file_menu.add_command(label='Add Project',command=self.unfinished)
self.menu.add_cascade(label='File',menu=self.file_menu)
self.config(menu=self.menu)
# Create the tabs (Graph, File Explorer, etc.)
self.notebook = Notebook(self)
graph_tab = tk.Frame(self.notebook)
file_explorer_tab = tk.Frame(self.notebook)
# Sets the Graph Tab as a Canvas where figures, images, etc. can be added
self.graph_tab = tk.Canvas(graph_tab)
self.graph_tab.pack(side=tk.TOP, expand=1)
# Sets the file explorer tab as a text box (change later)
self.file_explorer_tab = tk.Text(file_explorer_tab,bg='white',fg='black')
self.file_explorer_tab.pack(side=tk.TOP, expand=1)
# Add the tabs to the GUI
self.notebook.add(graph_tab, text='Graph')
self.notebook.add(file_explorer_tab, text='Files')
self.notebook.pack(fill=tk.BOTH, expand=1)
# Add the graph to the graph tab
self.fig = Figure()
graph = FigureCanvasTkAgg(self.fig,self.graph_tab)
graph.get_tk_widget().pack(side='top',fill='both',expand=True)
EllipseSlider(self.fig)
#------------------------------------------------------
def quit(self):
'''
Quit the program
'''
self.destroy()
#------------------------------------------------------
def unfinished(self):
'''
Messagebox for unfinished items
'''
msg.showinfo('Unfinished','This feature has not been finished')
#------------------------------------------------------
def random_graph(self):
x = list(range(0,10))
y = [i**3 for i in x]
fig = Figure()
axes = fig.add_subplot(111)
axes.plot(x,y,label=r'$x^3$')
axes.legend()
return fig
#----------------------------------------------------------
class EllipseSlider():
#------------------------------------------------------
def __init__(self,fig):
self.fig = fig
# Initial values
self.u = 0. #x-position of the center
self.v = 0. #y-position of the center
self.a = 2. #radius on the x-axis
self.b = 1.5 #radius on the y-axis
# Points to plot against
self.t = np.linspace(0, 2*np.pi, 100)
# Set up figure with centered axes and grid
self.ax = self.fig.add_subplot(111)
self.ax.set_aspect(aspect='equal')
self.ax.spines['left'].set_position('center')
self.ax.spines['bottom'].set_position('center')
self.ax.spines['right'].set_color('none')
self.ax.spines['top'].set_color('none')
self.ax.xaxis.set_ticks_position('bottom')
self.ax.yaxis.set_ticks_position('left')
self.ax.set_xlim(-2,2)
self.ax.set_ylim(-2,2)
self.ax.grid(color='lightgray',linestyle='--')
# Initial plot
self.l, = self.ax.plot(self.u+self.a*np.cos(self.t),
self.v+self.b*np.sin(self.t),'k')
# Slider setup
self.axcolor = 'lightgoldenrodyellow'
self.axb = self.fig.add_axes([0.25, 0.1, 0.65, 0.03], facecolor=self.axcolor)
self.axa = self.fig.add_axes([0.25, 0.15, 0.65, 0.03], facecolor=self.axcolor)
self.sb = Slider(self.axb, 'Y Radius', 0.1, 2.0, valinit=self.b)
self.sa = Slider(self.axa, 'X Radius', 0.1, 2.0, valinit=self.a)
# Call update as slider is changed
self.sb.on_changed(self.update)
self.sa.on_changed(self.update)
# Reset if reset button is pushed
self.resetax = self.fig.add_axes([0.8,0.025,0.1,0.04])
self.button = Button(self.resetax, 'Reset', color=self.axcolor, hovercolor='0.975')
self.button.on_clicked(self.reset)
# Color button setup
self.rax = self.fig.add_axes([0.025, 0.5, 0.15, 0.15], facecolor=self.axcolor)
self.radio = RadioButtons(self.rax, ('red', 'blue', 'green'), active=0)
self.radio.on_clicked(self.colorfunc)
#------------------------------------------------------
def update(self, val):
'''
Updates the plot as sliders are moved
'''
self.a = self.sa.val
self.b = self.sb.val
self.l.set_xdata(self.u+self.a*np.cos(self.t))
self.l.set_ydata(self.u+self.b*np.sin(self.t))
#------------------------------------------------------
def reset(self, event):
'''
Resets everything if reset button clicked
'''
self.sb.reset()
self.sa.reset()
#------------------------------------------------------
def colorfunc(self, label):
'''
Changes color of the plot when button clicked
'''
self.l.set_color(label)
self.fig.canvas.draw_idle()
#----------------------------------------------------------
if __name__ == '__main__':
luke_gui = LukeOutline()
luke_gui.mainloop()
es = EllipseSlider()
(UPDATE):
I have implemented the correction you showed and the code looks to work as intended except the vertical sliders I am using now do not update their position until I move the slider a second time. Please see the section from my code below:
# Call update if slider is changed
self.sa.on_changed(self.schedule_update)
self.sb.on_changed(self.schedule_update)
def update(self, value):
print(value)
self.vert_a.set_xdata(value)
self.vert_b.set_xdata(self.sb.val)
root.update()
def schedule_update(self, new_value):
if self.after_id:
root.after_cancel(self.after_id)
self.after_id = root.after(1000, self.update, new_value)
root = tk.Tk()
mainapp = MainApp(root)
root.mainloop()
Tkinter has a method named after for delaying the execution of a command. Your slider can use this to delay the effect of the slider for a second or two. If the slider moves, it can cancel the previously scheduled command and submit a new one.
Here's an example using plain tkinter for simplicity. Run the code and then move the slider quickly or slowly. You'll see that the label will only update after you haven't moved the slider for a full second.
import tkinter as tk
after_id = None
def schedule_update(new_value):
global after_id
if after_id:
root.after_cancel(after_id)
after_id = root.after(1000, update_label, new_value)
def update_label(new_value):
label.configure(text=f"New value: {new_value}")
root = tk.Tk()
label = tk.Label(root, text="", width=20)
scale = tk.Scale(
root, from_=1, to=100,
orient="horizontal", command=schedule_update
)
label.pack(side="top", fill="x", padx=20, pady=(10,0))
scale.pack(side="bottom", fill="x", padx=20, pady=10)
root.mainloop()
I have been trying to transfer some scripts behind a GUI (using Tkinter) and so far have made it thus far that any data that is opened is shown in a Tkinter canvas (using matplotlib to draw it).
The only problem that I have with this is that the standard zoom/scrolling that are in matplotlib (using left mouse button to 'move' the plot and right mouse button to 'zoom') are not accessible in the canvas, basically the functionality of the '4 pointed cross' in the matplotlib plot window.
I think this would require creating my own handlers but I would assume that there has to be a way to use the default handlers of matplotlib? I have also looked at 'scrolling' canvas options as mentioned in this question but those only seem to change the size of the plot area instead of zooming in/out on the data, also I do not want to add any further buttons just to manipulate the plot area.
The bare minimum code that I have currently:
#! /usr/bin/env python
from Tkinter import *
import matplotlib.pyplot as plt
import matplotlib.backends.backend_tkagg as tkagg
import tkFileDialog
class App():
def __init__(self,master):
# VARIABLES
self.inputFile = ""
self.fig = plt.Figure()
self.canvas = tkagg.FigureCanvasTkAgg(self.fig, master = master)
self.canvas.get_tk_widget().pack()
self.canvas.draw()
# FRAME
frame = Frame(master)
master.title("MassyTools 0.1.1 (Alpha)")
# VARIABLE ENTRIES
# BUTTONS
# MENU
menu = Menu(root)
root.config(menu = menu)
filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Open Input File", command = self.openFile)
calibmenu = Menu(menu)
menu.add_cascade(label="Calibrate",menu=calibmenu)
calibmenu.add_command(label="Open Calibration File", command = self.openCalibrationFile)
calibmenu.add_command(label="Calibrate", command = self.calibrateData)
def openFile(self):
file_path = tkFileDialog.askopenfilename()
setattr(self,'inputFile',file_path)
data = self.readData()
self.plotData(data)
def openCalibrationFile(self):
print "Place holder for selection of the calibration file"
def calibrateData(self):
print "Place holder for actual calibration"
def readData(self):
x_array = []
y_array = []
with open(self.inputFile,'r') as fr:
for line in fr:
line = line.rstrip('\n')
values = line.split()
x_array.append(float(values[0]))
y_array.append(float(values[1]))
return zip(x_array,y_array)
def plotData(self,data):
x_array = []
y_array = []
for i in data:
x_array.append(i[0])
y_array.append(i[1])
self.fig.clear()
self.axes = self.fig.add_subplot(111)
self.line, = self.axes.plot(x_array,y_array)
self.canvas.draw()
# Stuff that is not being used now but can be useful
"""def openFile(self,number):
name = tkFileDialog.askopenfilename()
ops = {
1: 'deglycoData',
2: 'peptideFile',
3: 'mzML'
}
setattr(self,ops[number],name)
"""
# End of 'stuff'
root = Tk()
app = App(root)
root.mainloop()
So you can affix a NavigationToolbar2TkAgg object to your canvas that will give you all the normal matplotlib methods and tools.
import matplotlib.backends.backend_tkagg as tkagg
# canvas is your canvas, and root is your parent (Frame, TopLevel, Tk instance etc.)
tkagg.NavigationToolbar2TkAgg(canvas, root)
A good example of its usage can be found here: Updating a graphs coordinates in matplotlib.
And an example of how to add custom methods to it can be found here (see class NavSelectToolbar(NavigationToolbar2TkAgg)).