Python利用Matplotlib和Tkinter在應用程序中內嵌圖表

在平常應用程序開發中,圖表(折線圖,柱狀圖等)以其直觀顯示,清晰明瞭的優點,使得應用範圍愈來愈普遍,本文以一個簡單的小例子,簡述如何將Tkinter和Matplotlib相互關聯起來,在應用程序中嵌入圖表,僅供學習分享使用,若有不足之處,還請指正。canvas

涉及知識點

  1. Tkinter 是Python內置的桌面程序開發組件庫,包含平常使用的基礎組件(如:Label,Button,Entry等),利用Tkinter能夠方便的開發可視化程序。
  2. Matplotlib 是一個開源的數據可視化類庫,利用matplotlib能夠繪製各類類型的圖表(如:折線圖,柱狀圖,散點圖等)。
  3. Numpy 是一個開源的數學相關的類庫,普遍應用於數學計算等領域。本例主要使用Numpy提供的數學函數和隨機數生成數據源。

操做步驟

若是要將matplotlib生成圖表和Tkinter生成的GUI程序關聯起來,須要如下3個步驟:windows

  1. 建立Matplotlib的figure(畫布)對象,並在figure上進行繪圖。
  2. 建立FigureCanvasTkAgg(畫布容器)對象,參數爲第1步生成的figure對象和容器存放的父對象,並調用建立對象的draw函數。
  3. 調用FigureCanvasTkAgg對應組件的Pack方法,將對象顯示在頁面上。

示例效果圖

將Matplotlib生成的曲線圖,嵌入到普通的windows程序中,以下圖所示:app

 

 核心代碼

建立圖表代碼dom

 1    def create_matplotlib(self):
 2         """建立繪圖對象"""
 3         # 設置中文顯示字體
 4         mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文顯示
 5         mpl.rcParams['axes.unicode_minus'] = False  # 負號顯示
 6         # 建立繪圖對象f figsize的單位是英寸 像素 = 英寸*分辨率
 7         self.figure = plt.figure(num=2, figsize=(7, 4), dpi=80, facecolor="gold", edgecolor='green', frameon=True)
 8         # 建立一副子圖
 9         fig1 = plt.subplot(1, 1, 1)  # 三個參數,依次是:行,列,當前索引
10         # 建立數據源:x軸是等間距的一組數
11         x = np.arange(-2 * np.pi, 2 * np.pi, 0.1)
12         y1 = np.sin(x)
13         y2 = np.cos(x)
14 
15         line1 = fig1.plot(x, y1, color='red', linewidth=2, label='y=sin(x)', linestyle='--')  # 畫第一條線
16         line2 = fig1.plot(x, y2, color='green', label='y=cos(x)')
17         plt.setp(line2, linewidth=1, linestyle='-', alpha=0.7)  # 華第二條線 color='',
18 
19         fig1.set_title("數學曲線圖", loc='center', pad=20, fontsize='xx-large', color='red')  # 設置標題
20         # line1.set_label("正弦曲線")  # 肯定圖例
21         # 定義legend 從新定義了一次label
22         fig1.legend(['正弦', '餘弦'], loc='lower right', facecolor='orange', frameon=True, shadow=True, framealpha=0.7)
23         # ,fontsize='xx-large'
24         fig1.set_xlabel('(x)橫座標')  # 肯定座標軸標題
25         fig1.set_ylabel("(y)縱座標")
26         fig1.set_yticks([-1, -1 / 2, 0, 1 / 2, 1])  # 設置座標軸刻度
27         fig1.grid(which='major', axis='x', color='gray', linestyle='-', linewidth=0.5, alpha=0.2)  # 設置網格
View Code

建立圖表容器,並顯示代碼ide

 1     def createWidget(self, figure):
 2         """建立組件"""
 3         self.label = Label(self, text='這是一個Tkinter和Matplotlib相結合的小例子')
 4         self.label.pack()
 5         # 建立畫布
 6         self.canvas = FigureCanvasTkAgg(figure, self)
 7         self.canvas.draw()
 8         self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
 9         # 把matplotlib繪製圖形的導航工具欄顯示到tkinter窗口上
10         # toolbar = NavigationToolbar2Tk(self.canvas, self)
11         # toolbar.update()
12         # self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
13         # self.button = Button(master=self, text="退出", command=quit)
14         # # 按鈕放在下邊
15         # self.button.pack(side=BOTTOM)
View Code

總體代碼及調用邏輯,以下所示:函數

 1 from tkinter import *
 2 import numpy as np
 3 import matplotlib
 4 import matplotlib.pyplot as plt
 5 from matplotlib.pylab import mpl
 6 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
 7 
 8 
 9 class Application(Frame):
10     """一個經典的GUI寫法"""
11 
12     def __init__(self, master=None):
13         '''初始化方法'''
14         super().__init__(master)  # 調用父類的初始化方法
15         self.master = master
16         self.pack(side=TOP, fill=BOTH, expand=1)  # 此處填充父窗體
17         self.create_matplotlib()
18         self.createWidget(self.figure)
19 
20     def createWidget(self, figure):
21         """建立組件"""
22         self.label = Label(self, text='這是一個Tkinter和Matplotlib相結合的小例子')
23         self.label.pack()
24         # 建立畫布
25         self.canvas = FigureCanvasTkAgg(figure, self)
26         self.canvas.draw()
27         self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
28         # 把matplotlib繪製圖形的導航工具欄顯示到tkinter窗口上
29         # toolbar = NavigationToolbar2Tk(self.canvas, self)
30         # toolbar.update()
31         # self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
32         # self.button = Button(master=self, text="退出", command=quit)
33         # # 按鈕放在下邊
34         # self.button.pack(side=BOTTOM)
35 
36     def create_matplotlib(self):
37         """建立繪圖對象"""
38         # 設置中文顯示字體
39         mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文顯示
40         mpl.rcParams['axes.unicode_minus'] = False  # 負號顯示
41         # 建立繪圖對象f figsize的單位是英寸 像素 = 英寸*分辨率
42         self.figure = plt.figure(num=2, figsize=(7, 4), dpi=80, facecolor="gold", edgecolor='green', frameon=True)
43         # 建立一副子圖
44         fig1 = plt.subplot(1, 1, 1)  # 三個參數,依次是:行,列,當前索引
45         # 建立數據源:x軸是等間距的一組數
46         x = np.arange(-2 * np.pi, 2 * np.pi, 0.1)
47         y1 = np.sin(x)
48         y2 = np.cos(x)
49 
50         line1 = fig1.plot(x, y1, color='red', linewidth=2, label='y=sin(x)', linestyle='--')  # 畫第一條線
51         line2 = fig1.plot(x, y2, color='green', label='y=cos(x)')
52         plt.setp(line2, linewidth=1, linestyle='-', alpha=0.7)  # 華第二條線 color='',
53 
54         fig1.set_title("數學曲線圖", loc='center', pad=20, fontsize='xx-large', color='red')  # 設置標題
55         # line1.set_label("正弦曲線")  # 肯定圖例
56         # 定義legend 從新定義了一次label
57         fig1.legend(['正弦', '餘弦'], loc='lower right', facecolor='orange', frameon=True, shadow=True, framealpha=0.7)
58         # ,fontsize='xx-large'
59         fig1.set_xlabel('(x)橫座標')  # 肯定座標軸標題
60         fig1.set_ylabel("(y)縱座標")
61         fig1.set_yticks([-1, -1 / 2, 0, 1 / 2, 1])  # 設置座標軸刻度
62         fig1.grid(which='major', axis='x', color='gray', linestyle='-', linewidth=0.5, alpha=0.2)  # 設置網格
63 
64     def destroy(self):
65         """重寫destroy方法"""
66         super().destroy()
67         quit()
68 
69     def quit():
70         """點擊退出按鈕時調用這個函數"""
71         root.quit()  # 結束主循環
72         root.destroy()  # 銷燬窗口
73 
74 
75 if __name__ == '__main__':
76     root = Tk()
77     root.title('數學曲線窗口')
78     root.geometry('560x400+200+200')
79     app = Application(master=root)
80 
81     root.mainloop()
View Code

多圖示例

如何利用Matplotlib在一張圖裏面,包含多張子圖,以下所示:工具

多圖核心代碼

其餘代碼和上例保持一致,只是在建立圖表時略有差別。主要是利用plt.subplot(2, 2, 1)方法對圖片進行切分。以下所示:oop

 1     def create_matplotlib(self):
 2         """建立繪圖對象"""
 3         # 設置中文顯示字體
 4         mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文顯示
 5         mpl.rcParams['axes.unicode_minus'] = False  # 負號顯示
 6         # 建立繪圖對象f figsize的單位是英寸 像素 = 英寸*分辨率
 7         self.figure = plt.figure(num=2, figsize=(7, 4), dpi=80, facecolor="gold", edgecolor='green', frameon=True)
 8         self.figure.text(0.45, 0.94, '這是四幅圖') # 設置顯示的文本
 9         # 一張圖上顯示4張小圖
10         x = np.linspace(-6, 6, 100)
11         y = np.sin(x)  # 正弦曲線
12         y2 = np.cos(x)  # 餘弦曲線
13         y3 = np.tan(x)  # tan函數
14         y4 = np.square(x)  # 平方函數
15         fig1 = plt.subplot(2, 2, 1)  # 先進行分塊,最後一個參數是序號
16         self.setplot(fig1, x, y, 'y=sin(x)', 'red')
17         fig2 = plt.subplot(2, 2, 2)
18         self.setplot(fig2, x, y2, 'y=cos(x)', 'green')
19         fig3 = plt.subplot(2, 2, 3)
20         self.setplot(fig3, x, y3, 'y=tan(x)', 'black')
21         fig4 = plt.subplot(2, 2, 4)
22         self.setplot(fig4, x, y4, 'y=square(x)', 'gold')
23 
24     def setplot(self, fig, x, y, text, color='r'):
25         """繪製子圖"""
26         line = fig.plot(x, y, color=color, label=text)
27         fig.set_xlabel('(x)橫座標')  # 肯定座標軸標題
28         fig.set_ylabel("(y)縱座標")
29         fig.grid(which='major', axis='x', color='gray', linestyle='-', linewidth=0.5, alpha=0.2)  # 設置網格
30         fig.legend(loc='lower right', facecolor='orange', frameon=True, shadow=True, framealpha=0.7)
View Code

柱狀圖示例

如何利用Matplotlib繪製柱狀圖,以下所示:學習

柱狀圖核心代碼

其餘代碼和上例保持一致,只是在建立圖表時略有差別。主要是經過bar 函數建立柱狀圖,以下所示:字體

 1     def create_matplotlib(self):
 2         """建立繪圖對象"""
 3         # 設置中文顯示字體
 4         mpl.rcParams['font.sans-serif'] = ['SimHei']  # 中文顯示
 5         mpl.rcParams['axes.unicode_minus'] = False  # 負號顯示
 6         # 建立繪圖對象f figsize的單位是英寸 像素 = 英寸*分辨率
 7         self.figure = plt.figure(num=2, figsize=(7, 4), dpi=80, facecolor="gold", edgecolor='green', frameon=True)
 8         self.figure.text(0.45, 0.94, '這是柱狀圖圖') # 設置顯示的文本
 9         x = np.arange(12)
10         y = np.random.uniform(0.5, 1.0, 12) * (1 - x / float(12))
11         loc = zip(x, y)  # 將x, y 兩兩配對
12         plt.ylim(0, 1.2)  # 設置y軸的範圍
13         plt.bar(x, y, facecolor='green', edgecolor='black')  # 繪製柱狀圖(填充顏色綠色,邊框黑色)
14         for x, y in loc:
15             plt.text(x + 0.1, y + 0.01, '%.2f' % y, ha='center', va='bottom')  # 保留小數點2位
View Code

備註

Matplotlib的圖表形式還有不少,本例只是拋磚引玉,簡述兩種圖表的生成方式,其餘的圖表則不作贅述。

如需源碼連接,可點擊連接下載。一首小詞,舒緩一下心情。

浣溪沙·堤上游人逐畫船

宋代:歐陽修

堤上游人逐畫船,拍堤春水四垂天。綠楊樓外出鞦韆。 白髮戴花君莫笑,六幺催拍盞頻傳。人生何處似樽前!
相關文章
相關標籤/搜索