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.
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.
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()
Next is how to embed a matploblib graph in Tkinter. The procedure is explained using the figure below.
(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.
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()
(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.
Recommended Posts