在日常應用程序開發中,圖表(折線圖,柱狀圖等)以其直觀顯示,清晰明了的優勢,使得應用范圍越來越廣泛,本文以一個簡單的小例子,簡述如何將Tkinter和Matplotlib相互關聯起來,在應用程序中嵌入圖表,僅供學習分享使用,如有不足之處,還請指正。
涉及知識點
- Tkinter 是Python內置的桌面程序開發組件庫,包含日常使用的基礎組件(如:Label,Button,Entry等),利用Tkinter可以方便的開發可視化程序。
- Matplotlib 是一個開源的數據可視化類庫,利用matplotlib可以繪制各種類型的圖表(如:折線圖,柱狀圖,散點圖等)。
- Numpy 是一個開源的數學相關的類庫,廣泛應用於數學計算等領域。本例主要使用Numpy提供的數學函數和隨機數生成數據源。
操作步驟
如果要將matplotlib生成圖表和Tkinter生成的GUI程序關聯起來,需要以下3個步驟:
- 創建Matplotlib的figure(畫布)對象,並在figure上進行繪圖。
- 創建FigureCanvasTkAgg(畫布容器)對象,參數為第1步生成的figure對象和容器存放的父對象,並調用創建對象的draw函數。
- 調用FigureCanvasTkAgg對應組件的Pack方法,將對象顯示在頁面上。
示例效果圖
將Matplotlib生成的曲線圖,嵌入到普通的windows程序中,如下圖所示:
核心代碼
創建圖表代碼

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) # 設置網格
創建圖表容器,並顯示代碼

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)
整體代碼及調用邏輯,如下所示:

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()
多圖示例
如何利用Matplotlib在一張圖里面,包含多張子圖,如下所示:
多圖核心代碼
其他代碼和上例保持一致,只是在創建圖表時略有差異。主要是利用plt.subplot(2, 2, 1)方法對圖片進行切分。如下所示:

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)
柱狀圖示例
如何利用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位
備注
Matplotlib的圖表形式還有很多,本例只是拋磚引玉,簡述兩種圖表的生成方式,其他的圖表則不做贅述。
如需源碼鏈接,可點擊鏈接下載。一首小詞,舒緩一下心情。
浣溪沙·堤上游人逐畫船
宋代:歐陽修
堤上游人逐畫船,拍堤春水四垂天。綠楊樓外出秋千。
白發戴花君莫笑,六幺催拍盞頻傳。人生何處似樽前!
白發戴花君莫笑,六幺催拍盞頻傳。人生何處似樽前!