[PYTHON] Embed matplotlib graphs in Tkinter

1.First of all

Recently, there were the following hurdles regarding programming.

(1) I want to create a GUI program in Python. → OK using Tkinter (2) I want to display some calculation results on a graph. → OK with matplotlib (3) I want to embed the graph written by matplotlib in (2) in Tkinter in (1). → NG

I tried to get over it by playing with the example code, but it didn't work.

This article introduces the contents of how the problem (3) was solved.

2. Object-oriented design of matplotlib

First, I found that I needed to understand the object orientation of matplotlib. The graph created by matplotlib.pyplot is an object of Figure class, an object of Axes class that draws the actual graph, and an object (hereinafter, instance) of Axis class that manages x-axis and y-axis as follows. It consists of three parts.

(Note: Axes in English means axis, but in matplotlib it means the part that draws the graph, not the axis.)

Now let's draw a simple graph using matplotlib's object-oriented design.

(1) Generate a fig that is one figure instance.

fig = plt.figure()

(2) Generate four Axes instas to draw the actual graph.

ax1, ax2, ax3, ax4

(3) Arrange and draw the four Axes instas in a (2X2) matrix on the fig instas.

ax1 = fig.add_subplot(221) ax2 = fig.add_subplot(222) ax3 = fig.add_subplot(223) ax4 = fig.add_subplot(224) plt.show() The drawing result is displayed in the following figure. You can tell that it is Matplotlib by the round icon (upper left) of this window. matplotlib.png

The program code of the object-oriented design of matplotlib is posted.

import numpy as np
import matplotlib.pyplot as plt

#Prepare Data
x1 = np.linspace(0.0, 5.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
x2 = np.linspace(0.0, 3.0)
y2 = np.cos(2 * np.pi * x2) * np.exp(-x1)


# Figure instance
fig = plt.figure()
print(type(fig))

#ax1 instance
ax1 = fig.add_subplot(221)
ax1.plot(x1, y1)
ax1.set_title('line plot')
ax1.set_ylabel('Damped oscillation')
print(type(ax1))

#ax2 instance
ax2 = fig.add_subplot(222)
ax2.scatter(x1, y1, marker='o')
ax2.set_title('Scatter plot')

#ax3 instance
ax3 = fig.add_subplot(223)
ax3.plot(x2,y2)
ax3.set_ylabel('Damped oscillation')
ax3.set_xlabel('time (s)')

#ax4 instance
ax4 = fig.add_subplot(224)
ax4.scatter(x2, y2, marker='o')
ax4.set_xlabel('time (s)')

#Drawing
plt.show()

3. Embed matplotlib in Tkinter

Next is how to embed a matploblib graph in Tkinter. The procedure is explained using the figure below.

nagare.png

(1) Prepare a Tkinter window. Name the instance root. (2) Place a canvas instance on top of root. (3) Prepare a fig instance with a graph drawn in the same way as in the previous chapter. (4) Place the fig instance on the canvas instance and draw it.

It's complicated because there are three instances. However, if you keep this concept in mind, GUI programming from the next time will be easier.

The following code would perform steps (2) and (4) above. Be careful when using FigureCanvasTkAgg.

canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
canvas.draw()
canvas.get_tk_widget().pack()

The drawing result is displayed in the following figure. I was able to draw a matplot graph on the GUI well. You can tell that it is Tkinter from the blue feather icon (upper left) of this window.

I will post the program code to embed the graph of matplotlib in Tkinter. While maintaining the program code of the previous chapter, the contents of the Tkinter part will be expanded in the latter half.

tkinter.png
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk

# Prepare Data
x1 = np.linspace(0.0, 5.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
x2 = np.linspace(0.0, 3.0)
y2 = np.cos(2 * np.pi * x2) * np.exp(-x1)

# Figure instance
fig = plt.Figure()

# ax1
ax1 = fig.add_subplot(221)
ax1.plot(x1, y1)
ax1.set_title('line plot')
ax1.set_ylabel('Damped oscillation')

# ax2
ax2 = fig.add_subplot(222)
ax2.scatter(x1, y1, marker='o')
ax2.set_title('Scatter plot')

# ax3
ax3 = fig.add_subplot(223)
ax3.plot(x2, y2)
ax3.set_ylabel('Damped oscillation')
ax3.set_xlabel('time (s)')

# ax4
ax4 = fig.add_subplot(224)
ax4.scatter(x2, y2, marker='o')
ax4.set_xlabel('time (s)')


# When windows is closed.

def _destroyWindow():
    root.quit()
    root.destroy()


# Tkinter Class

root = tk.Tk()
root.withdraw()
root.protocol('WM_DELETE_WINDOW', _destroyWindow)  # When you close the tkinter window.

# Canvas
canvas = FigureCanvasTkAgg(fig, master=root)  # Generate canvas instance, Embedding fig in root
canvas.draw()
canvas.get_tk_widget().pack()
#canvas._tkcanvas.pack()

# root
root.update()
root.deiconify()
root.mainloop()

4. Summary

(1) I want to embed a graph written in matplotlib in Tkinter, but it didn't work. (2) First, you need to draw a matplotlib grab in an object-oriented design. (3) Then, prepare a canvas instance of Tkinter and put an instance of matplotlib graph on it.

5. Reference materials

  1. Matplotlib Usage https://matplotlib.org/1.5.1/faq/usage_faq.html
  2. Basic knowledge of matplotlib that I wanted to know early https://qiita.com/skotaro/items/08dc0b8c5704c94eafb9
  3. Embedding in Tk https://matplotlib.org/3.1.1/gallery/user_interfaces/embedding_in_tk_sgskip.html
  4. Tkinter event binding https://cassiopeia.hatenadiary.org/entry/20070822/1187712650

Recommended Posts

Embed matplotlib graphs in Tkinter
Dynamically generate graphs with matplotlib and embed in PDF with reporlab
I want to embed Matplotlib in PySimpleGUI
View images in Matplotlib
Tab app in Tkinter
2D plot in matplotlib
Animate multiple graphs with matplotlib
Embed wav files in Jupyter
Two ways to display multiple graphs in one image with matplotlib
[Python] Show multiple windows in Tkinter
Show axes as percentages in Matplotlib
Set opset to embed in ONNX
Implement a date setter in Tkinter
Embed your favorite HTML in Jupyter
Draw retention rate graph in Matplotlib
View graphs inline in Jupyter Notebook
Heatmap with Dendrogram in Python + matplotlib
Make matplotlib Japanese compatible in 3 minutes
Show dividing lines in matplotlib histogram
Easy to draw graphs with matplotlib
The first step in Python Matplotlib
GUI creation in python using tkinter 2
[Small story] How to save matplotlib graphs in a batch with Jupyter
Eliminate garbled Japanese characters in matplotlib graphs in Cloud Pak for Data Notebook