Displaying matplotlib inside Tkinter - python

I have matplotlib script that reads an Excel file and draws it. (as MATPLOT)
And i made another python script looks like a normal program (topmenu, statusbar..) (as GUI)
I want to display MATPLOT in my GUI. Is there any way to call all of the script inside the MATPLOT to run in GUI? Like embedding a video to another website.
root = Tk()
root.geometry("800x600")
#MENU
topMenu = Menu(root)
root.config(menu=topMenu)
loadMenu = Menu(topMenu, tearoff=0)
topMenu.add_cascade(label="File", menu=loadMenu)
loadMenu.add_command(label="Import New", command=doNothing)
loadMenu.add_command(label="Show 'Filter' Menu" , command=showOptions)
loadMenu.add_separator()
loadMenu.add_command(label="Exit", command=root.quit)
#GRAPH
#
#StatusBar
status = Label(root, text="File Name:", bd=1, relief=SUNKEN, anchor=W)
status.pack(side=BOTTOM, fill=X)
root.mainloop()

How to embed a matplotlib Figure in a tkinter Frame
The approach presented subclasses tk.Frame and matplotlib.figure.Figure to make it easy to re-use the code for other purposes.
It creates a tkFrame, with all the boilerplate ready to accept and display a matplotlib Figure.
It then creates a Figure (again, ready to be modified and expanded), and embeds it in the tk.Frame created above.
Last, it launches the tk.mainloop
import matplotlib
import tkinter as tk
matplotlib.use('TkAgg')
# from matplotlib import style
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
class GraphPage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.title_label = tk.Label(self, text="Graph Page Example")
self.title_label.pack()
self.pack()
def add_mpl_figure(self, fig):
self.mpl_canvas = FigureCanvasTkAgg(fig, self)
self.mpl_canvas.show()
self.mpl_canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.toolbar = NavigationToolbar2TkAgg(self.mpl_canvas, self)
self.toolbar.update()
self.mpl_canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
class MPLGraph(Figure):
def __init__(self):
Figure.__init__(self, figsize=(5, 5), dpi=100)
self.plot = self.add_subplot(111)
self.plot.plot([1, 2, 3, 4, 5, 6, 7], [4, 3, 5, 0, 2, 0, 6])
fig = MPLGraph()
root = tk.Tk()
graph_page = GraphPage(root)
graph_page.add_mpl_figure(fig)
root.mainloop()

Related

Tkinter scrollbar is off the screen and doesn't scroll

So I've created a GUI and I need a vertical scrollbar, however the scrollbar seems to be taller than its parent frame, and doesn't scroll. I have no idea why but here's the code I have so far:
import tkinter as Tk
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
root = Tk.Tk()
RightPane = Tk.Frame(root)
RightPane.grid()
class Graph:
#Draws and return a placeholder for a graph
##param parent is the Tk.Frame parent obj
##param title is the (string) title for the graph
def __init__(self, parent, title=''):
#Initialise graph
self.title = title
self.fig = Figure(figsize=(4,4))
self.plot = self.fig.add_subplot()
self.plot.set_title(self.title, fontsize=10)
self.plot.set_ylim(top=1)
self.plot.set_xlim(right=255)
self.plot.set_ylabel("Certainty", fontsize=8)
self.plot.set_xlabel("Pixel Value", fontsize=8)
#Draw
self.canvas = FigureCanvasTkAgg(self.fig, master=parent)
self.canvas.get_tk_widget().pack()
self.canvas.draw()
return
#Result Graphs -------------------------------------------
ResultFrame = Tk.Frame(RightPane)
ResultFrame.grid_columnconfigure(0, weight=1)
ResultFrame.grid(row=2, column=2, rowspan=14, padx=(10,0), pady=(10,0), sticky='nwe')
ResultScrollable = Tk.Canvas(ResultFrame)
ResultScrollable.grid(row=0, column=0, padx=(5,0), sticky='we')
graphCollection = []
for i in range(10):
title = 'Certainty that image is digit: {}'.format(i)
graphCollection.append(Graph(ResultScrollable, title=title))
ResultFrameVbar = Tk.Scrollbar(ResultFrame, orient='vertical', command=ResultScrollable.yview)
ResultFrameVbar.grid(row=0, column=1, sticky='nswe')
ResultScrollable.config(yscrollcommand=ResultFrameVbar.set, scrollregion=ResultScrollable.bbox('all'))
root.mainloop()
Couldn't find anything on the internet, so any help would really be appreciated. Thank you in advance.
You are creating canvases (self.canvas) inside canvas (ResultScrollable) and using pack() on those canvases. So ResultScrollable.bbox('all') will not include those canvases. You should create an internal Frame and assocate it with create_window(), then put those canvases inside the internal Frame:
internalFrame = Tk.Frame(ResultScrollable)
ResultScrollable.create_window(0, 0, window=internalFrame, anchor='nw')
graphCollection = []
for i in range(10):
title = 'Certainty that image is digit: {}'.format(i)
graphCollection.append(Graph(internalFrame, title=title))

How to resize matplotlib graph in tkinter window

I'm trying to set up some program that includes a matplotlib graph and tkinter buttons and whatnot below it. However, the matplotlib graph occupies the entire window overlaying the tkinter buttons and stuff.
I'd tried using pack, but it doesn't let me put stuff side by side, so I'd like the tkinter widgets to be arranged with .grid or coordinates.
from tkinter import *
from tkinter import StringVar
import tkinter
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
def eggs():
print("eggs")
root = Tk()
root.geometry("600x600")
root.title("eggs")
fig = Figure(figsize=(10, 6), dpi=100)
x = [1,2,3,4]
y = [1,2,3,4]
AS = [10/2**0]
fig.add_subplot(111).plot(x,y)
#fig.add_subplot(111).plot(AS)
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
testbutton = Button(root, text = "test button", command = eggs)
testbutton.place(x=100, y=550)
root.mainloop()
Wanting the top part of the window to be occupied by the graph and the buttons and other additional stuff below it.
You can use one Frame to keep graph and its toolbar vertically, and another Frame to keep buttons horizontally. And then you can use pack() to put one Frame at top top and other at the bottom.
The only problem makes figsize=(10, 6) which needs more space than "600x600"
BTW: you can use Button(toolbar, ...) to add button to NavigationToolbar2Tk - see "my tool".
]1
import tkinter as tk
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
# --- functions ---
def eggs():
print("eggs")
# --- main ---
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10/2**0]
# ---
root = tk.Tk()
root.geometry("600x600")
root.title("eggs")
# ---
frame_top = tk.Frame(root)
frame_top.pack(fill='both', expand=True)
fig = Figure(dpi=100) # figsize=(10, 6),
fig.add_subplot(111).plot(x,y)
#fig.add_subplot(111).plot(AS)
canvas = FigureCanvasTkAgg(fig, master=frame_top) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(fill='both', expand=True)
toolbar = NavigationToolbar2Tk(canvas, frame_top)
toolbar.update()
tool = tk.Button(toolbar, text="my tool")
tool.pack(side='left')#, fill='x', expand=True)
# ---
frame_bottom = tk.Frame(root)
frame_bottom.pack(fill='x')
button1 = tk.Button(frame_bottom, text="button1")
button1.pack(side='left', fill='x', expand=True)
button2 = tk.Button(frame_bottom, text="button2")
button2.pack(side='left', fill='x', expand=True)
button3 = tk.Button(frame_bottom, text="button3")
button3.pack(side='left', fill='x', expand=True)
# ---
root.mainloop()

Overlay graph in tkinter

I am making an embeded matplotlib graph GUI program.
I want to make overlaid graphs in upper graph window when users click the "Update" button.
But, There is no response when I click "Update" button.
I am using Spyder Python 3.6 Version.
Below is what I wrote.
import matplotlib.pyplot as plt
import csv
import numpy as np
import tkinter as tk
from tkinter import ttk
import matplotlib as plt
plt.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from matplotlib import style
class Analysis_app(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
tk.Tk.wm_title(self, "SIM Analyser")
right_f = tk.Frame(self)
right_f.pack(side=tk.RIGHT)
self.entry1 = ttk.Entry(right_f).pack()
self.entry2 = ttk.Entry(right_f).pack()
self.entry3 = ttk.Entry(right_f).pack()
self.entry4 = ttk.Entry(right_f).pack()
self.entry5 = ttk.Entry(right_f).pack()
Button1 = ttk.Button(right_f, text='Update', command=self.plot).pack(side=tk.BOTTOM)
self.left_f = tk.Frame(self)
self.left_f.pack(side=tk.LEFT)
f = Figure(figsize=(10,6), dpi=100)
self.upplot = f.add_subplot(211)
self.botplot = f.add_subplot(212)
a =self.upplot
a.clear()
a.plot([1,2,3],[1,2,3])
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2TkAgg(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.mainloop()
def plot(self):
a =self.upplot
a.clear()
a.plot([1,2,3],[5,2,5])
You get no response because the canvas is not redrawn after changing the content of the plot.
The solution is to replace canvas = FigureCanvasTkAgg(f, self) by self.canvas = FigureCanvasTkAgg(f, self) so that you can redraw the canvas in self.plot:
def plot(self):
a = self.upplot
a.clear()
a.plot([1,2,3],[5,2,5])
self.canvas.draw_idle()
And then you should see the change after clicking on the update button.

Tkinter canvas and items that can use Matplotlib Toolbar?

I have written a small GUI program with Tkinter because I like the ability to queue updates to the mainloop for successive item updates in order to create an interative animation of changing circle colors that are induced by data changes.
( this is something I have found matplotib to not play nicely with, i.e. if I use patches and I want to update the color of the patch I have found that I have to add a new patch on top of the existing patch, which leaves color residue)
However, I would like to benefit from Matplotlib's Toolbar so that I can use the zoom and panning functionality.
I am experimenting on how to do this with a small test program for simplicity and have gotten matplotlib and tkinter in the same window... BUT the zoom doesnt work!
I have 2 weeks experience with Matplotlib and a couple days with Tkinter so please correct me on any inaccurate statements or add additional suggestions.
Here is the small program I have written for testing in which the matplotlib zoom doesn't work:
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import sys
from Tkinter import *
import matplotlib.backends.backend_tkagg as tkagg
class App:
def __init__(self, master):
self.frame = Frame(master, bg='#FFFFFF', height=1000, width=1000,
borderwidth=1, relief=RAISED)
self.frame.pack(expand=YES, fill=BOTH)
self.button = Button(
self.frame, text="QUIT", fg="red", command=self.frame.quit
)
self.button.pack(side=BOTTOM)
self.hi_there = Button(self.frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=BOTTOM)
###
# Creating a canvas for Tk items
self.tkcanvas = Canvas(self.frame, height=600, width=600)
self.tkcanvas.config(background='yellow')
self.tkcanvas.pack()
self.tkcanvas.create_rectangle(0,0,100,100,fill='blue')
# Hoping to utilize the mpl toolbar for zooming function by doing:
self.fig = Figure(figsize=(4,.5))
self.mplcanvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.mplcanvas.get_tk_widget().pack(side='bottom', fill='both')
self.mplcanvas._tkcanvas.pack(side='bottom', fill='both', expand=1)
#
self.mpltoolbar = NavigationToolbar2TkAgg( self.mplcanvas, master )
self.mpltoolbar.update()
self.mpltoolbar.pack()
###
def say_hi(self):
print "hi there, everyone!"
root = Tk()
app = App(root)
root.mainloop()
root.destroy()

Black box around matplotlib graph in Tkinter

I'm embedding a pyplot graph in a Tkinter frame. There's a thick black line around the entire figure that I'd like to get rid of. It only appears when my Tkinter window is actively selected:
I'm using Python 2.7.6 on Mac OS 10.9. Here's my code:
from Tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class PlotFrame(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.fig = plt.figure()
self.plot = self.fig.add_subplot(1, 1, 1)
self.canvas = FigureCanvasTkAgg(self.fig, master=self)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=0, sticky=(N), padx=20, pady=20)
root = Tk()
plot_frame = PlotFrame(root)
plot_frame.grid(row=0, column=0)
root.mainloop()
Thanks!
That is controlled by the highlightthickness and highlightcolor attributes of the canvas widget. Set highlightthickness to zero if you don't want to see it.

Categories