Integrating Matplotlib
Here are resources and additional documentation about Matplotlib and PySimpleGUI:
00:00 Integrating Matplotlib With PySimpleGUI. Creating graphs is a great way to share information with your colleagues. One of the most popular graphing packages for Python is Matplotlib.
00:13 Matplotlib can create all kinds of different graphs. If you’d like to know more about it, check out Python Plotting With Matplotlib. Matplotlib can be integrated with PySimpleGUI, so you can add graphs to your GUI fairly easily if you already know how to use Matplotlib.
00:32
If you don’t have Matplotlib installed, then you can do so using pip
. Note that other libraries will be installed as well, including NumPy.
00:43
Now that you have all the pieces you need to write the code, you can create a new file called psg_matplotlib.py
. The demo code is a little long, so let’s look at it in pieces starting with this first section.
00:59
These are the imports you’ll need to make your code work. This code also sets up the Matplotlib Figure()
and adds a plot using .add_subplot()
. For more details, you may want to refer to the documentation.
01:17
The PySimpleGUIQt port doesn’t work in the same way currently, but that’s being worked on for a future release. In both PySimpleGUI and Tkinter, you use the Canvas()
element for drawing.
01:29
You can read more about that in the documentation. Now you can create a helper function to draw the figure on PySimpleGUI’s Canvas()
. A helper function is repetitive code that you don’t want to write multiple times.
01:43
Onscreen, you can see the helper function being written. It uses the .draw()
method to draw the plots to PySimpleGUI’s Canvas()
element.
01:52
To use PySimpleGUI’s Canvas()
, you need to pass it into FigureCanvasTkAgg()
along with the Matplotlib figure
object. FigureCanvasTkAgg()
comes from Matplotlib and is used by Tkinter to embed the plots in PySimpleGUI.
02:08
This would work differently if you were using PySimpleGUIQt. The last step is to write the user interface with PySimpleGUI. This is simpler than the previous image viewer interface, as the layout
only consists of three elements.
02:26
To create the user interface, all you need is a Text()
element, a Canvas()
element, and a Button()
element.
02:38
Then all of these are added to a Window()
,
02:59
and you can call your draw_figure()
helper function to draw the plot.
03:11 You don’t need the event loop here because you won’t be interacting with the elements in this user interface. Now you can see the program running.
03:27 There are other Matplotlib demos included with PySimpleGUI that you should check out. Now that you’ve seen how to integrate Matplotlib with PySimpleGUI, in the next section you’ll see how to integrate computer vision with the OpenCV library.
Darren Jones RP Team on Dec. 22, 2022
@Michel - Can you post the code that did work and the code that didn’t?
Michel on Dec. 24, 2022
Hi Darren
Sorry for the late reply, below the code that didn’t work and the error message. (the code that did the trick is commented out)
# psg_matplotlib.py
import PySimpleGUI as sg
import matplotlib
# import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
# fig = plt.figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
matplotlib.use('TkAgg')
def draw_figure(canvas, figure):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
# define the window layout
layout = [
[sg.Text('Plot test')],
[sg.Canvas(key='-CANVAS-')],
[sg.Button('Ok')],
]
# create the form and show it without the plot
window = sg.Window(
'Matplotlib Single Graph',
layout,
location=(0 ,0),
finalize=True,
element_justification='center',
font='Helvetica 18',
)
# add the plot to the window
draw_figure(window['-CANVAS-'].TKCanvas, fig)
event, values = window.read()
window.close()
Error message:
line 224, in __getattr__
raise AttributeError(AttributeError: module 'matplotlib' has no attribute 'figure'
Also found this in init.py
"""
For the most part, direct use of the explicit object-oriented library is
encouraged when programming; the implicit pyplot interface is primarily for
working interactively. The exceptions to this suggestion are the pyplot
functions `.pyplot.figure`, `.pyplot.subplot`, `.pyplot.subplots`, and
`.pyplot.savefig`, which can greatly simplify scripting. See
:ref:`api_interfaces` for an explanation of the tradeoffs between the implicit
and explicit interfaces.
"""
Darren Jones RP Team on Dec. 29, 2022
Hi Michel. On the face of it you may think that you could change the line
fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
To
fig = matplotlib.pyplot.figure.Figure(figsize=(5, 4), dpi=100)
to make it work, but pyplot doesn’t work in that way - it doesn’t work in the way that many modules do where you can import a sub-module and get all the functionality, or import the whole module and drill down using . notation.
If you look at the source code of matplotlib on github - github.com/matplotlib/matplotlib - in the lib folder, you’ll see that pyplot isn’t a folder with other folders in it and with an __init__.py
, so you need to import it directly (typically aliased as plt) and then make use of it from there as plt.figure, etc.
If you have a look at the code of pyplot - github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/pyplot.py - you can see that there are a lot of imports at the top of the file (which means the code in this file is run, so all the imports are executed), and that’s why you need to import pyplot in this manner (so that the file is executed and the imports happen).
If you try to access Figure directly, while matplotlib.figure
does exist (and it’s in the files in the github repo), matplotlib.figure.Figure
doesn’t exist, because it’s not imported as part of the matplotlib __init__.py
import process.
However, if you want to, you can have the following imports (which import matplotlib but also Figure directly):
import matplotlib
from matplotlib.figure import Figure
and then change the fig creation line to
fig = Figure(figsize=(5, 4), dpi=100)
and that will work… but it’s a convoluted way to access Figure()
, so I’d stick to importing pyplot in the recommended method!
toigopaul on Jan. 20, 2024
Darren,
I’m really looking forward to including graphs on my tkinter windows. Thanks!
However, similar to @Michel, I get hung up with an
AttributeError: module ‘matplotlib’ has no attribute ‘figure’
unless I add:
from matplotlib.figure import Figure
Darren Jones RP Team on Jan. 23, 2024
Hi toigopaul! It sounds like you have similar issues to Michel - can you post the code that isn’t working (unless you add the stated import)? It sounds like a pretty similar situation to his.
toigopaul on Jan. 23, 2024
# GUI_psg_matplotlib
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib
fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t,2*np.sin(2*np.pi*t))
matplotlib.use("TkAgg")
def draw_figure(canvas, figure):
figure_canvas_agg=FigureCanvasTkAgg(figure,canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(
side="top",fill="both",expand=1
)
return figure_canvas_agg
# define window layout
layout = [
[sg.Text("Plot test")],
[sg.Canvas(key="-CANVAS-")],
[sg.Button("Ok")]
]
# create form and show without plot
window = sg.Window(
"Matplotlib single graph",
layout,
location=(0,0),
finalize=True,
element_justification="center",
font="Helvetica 18"
)
# add the plot to the window
draw_figure(window["-CANVAS-"].TKCanvas, fig)
event, values = window.read()
window.close()
Become a Member to join the conversation.
Michel on Dec. 17, 2022
Hi Darren,
Thank you for the excellent tutorial.
I got on error message on matlotlib.figure…
Instead after importing matplotlib.pyplot as plt I was able to make it work. But both options should work right?
(see code below)