目錄
[TOC]python
前言
前一章節,咱們解讀了tkinter內嵌Matplotlib的教程,瞭解其內嵌的原理,就是在tkinter建立matplotlib的畫布控件,再利用其返回的畫布對象進行繪圖,其餘附加功能,使用tkinter控件實現。編程
(一)對matplotlib畫布的封裝:
(1)說明:
咱們但願對官方的實例代碼進行封裝成一個函數,並返回一個畫布對象,外部再調用該函數,並獲取畫布對象,進行繪製操做。canvas
(2)封裝後的代碼:
""" 畫布文件,實現繪圖區域的顯示,並返回畫布的對象。 """ import tkinter as tk # 建立畫布須要的庫 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # 建立工具欄須要的庫 from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk # 快捷鍵須要的庫 from matplotlib.backend_bases import key_press_handler # 導入畫圖經常使用的庫 from matplotlib.figure import Figure def plot_fun(root): """ 該函數實現的是內嵌畫布,不負責畫圖,返回畫布對象。 :param root:父親控件對象, 通常是容器控件或者窗體 :return: 畫布對象 """ # 畫布的大小和分別率 fig = Figure(dpi=100) axs = fig.add_subplot(111) # 建立畫布 canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea. canvas.draw() # 顯示畫布 canvas.get_tk_widget().pack() # 建立工具條 toolbar = NavigationToolbar2Tk(canvas, root) toolbar.update() # 顯示工具條 canvas.get_tk_widget().pack() # 調用快捷鍵 def on_key_press(event): key_press_handler(event, canvas, toolbar) canvas.mpl_connect("key_press_event", on_key_press) # 返回畫布的對象 return axs
(二)思路分析:
1.需求說明:
(1)背景:
做爲學生的咱們,你是否有那麼一個場景,唉……,這個數學函數好難求哦,要是知道它的圖像這麼畫就行了。app
(2)需求:
給出數學表達式,繪製出該數學表達式的函數曲線,一來能夠觀察函數的變化趨勢,二來能夠根據兩條曲線的交點,來求解出方程的大體結果。框架
2.框架的設置:
(1)說明:
分模塊編程,向來是衆人所提倡的,再python裏更是很好的實現。函數
再動手敲代碼以前,咱們先來大體的設置一下,小項目的框架。工具
(2)框架圖解:
3.文件說明:
(1)main.py
主程序文件,負責程序的啓動與結束和窗體的大體設置。oop
(2)widget.py
控件文件,負責程序控件的建立與佈局佈局
(3)figure.py
畫布文件,實現繪圖區域的顯示,並返回畫布的對象。url
(4)plot.py
繪圖文件,負責函數曲線的繪製
(三)各文件的源代碼
1.main.py
""" 主程序文件,負責程序的啓動與結束和窗體的大體設置。 """ import tkinter as tk import widget def win_w_h(root): """ 控制窗口的大小和出現的位置 :param root: :return: 窗口的大小和出現的位置 """ # 設置標題: win.title("數學函數繪圖") # 繪圖區標籤 label_plot = tk.Label(root, text="繪 圖 區", font=("微軟雅黑", 10), fg="blue") label_plot.place(relx=0.26, rely=0) label_func = tk.Label(root, text="功 能 區", font=("微軟雅黑", 10), fg="blue") label_func.place(relx=0.75, rely=0) # 獲取屏幕的大小; screen_height = root.winfo_screenheight() screen_width = root.winfo_screenwidth() # 窗體的大小 win_width = 0.8 * screen_width win_height = 0.8 * screen_height # 窗體出現的位置:控制的是左上角的座標 show_width = (screen_width - win_width) / 2 show_height = (screen_height - win_height) / 2 # 返回窗體 座標 return win_width, win_height, show_width, show_height win = tk.Tk() # 大小 位置 win.geometry("%dx%d+%d+%d" % (win_w_h(win))) # 建立一個容器, 沒有畫布時的背景 frame1 = tk.Frame(win, bg="#c0c0c0") frame1.place(relx=0.00, rely=0.05, relwidth=0.62, relheight=0.89) # 控件區 frame2 = tk.Frame(win, bg="#808080") frame2.place(relx=0.62, rely=0.05, relwidth=0.38, relheight=0.89) # 調用控件模塊 widget.widget_main(win, frame2) win.mainloop()
2.widget.py
""" 控件文件,負責程序控件的建立與佈局 """ import tkinter as tk # 對話框所需的庫 import tkinter.messagebox as mb # 畫布文件 import figure # 繪圖文件 import plot def widget_main(win, root): """ 負責程序控件的建立與佈局 :param win: 主窗體的對象。 :param root: 繪圖區的容器對象。 :return: 無 """ # 控件區的容器對象 frame1 = None # ===========功能區============================ # 繪圖的功能函數 def plot_f(): string = entry.get() # 判斷輸入框是否爲空 if string == "": mb.showerror("提示", "沒有輸入值,請從新輸入:") else: # 判斷是否已經建立畫布 if frame1==None: mb.showerror("提示", "沒有建立畫布,不能畫圖,請先建立畫布") else: axs = figure.plot_fun(frame1) plot.plot_main(string, axs) # 清除的功能函數 def clear(): nonlocal frame1 entry.delete(0, "end") if frame1==None: mb.showerror("提示", "已經沒有畫布,沒法清除畫布") else: frame1.destroy() frame1 = None # 建立畫布的功能函數 def create(): nonlocal frame1 if frame1 != None: mb.showerror("提示", "畫布已經存在,請不要重複建立畫布") else: frame1 = tk.LabelFrame(win, bg="#80ff80", text="畫-----布", labelanchor="n", fg="green") frame1.place(relx=0.00, rely=0.05, relwidth=0.62, relheight=0.95) # =============控件區====================== # 標籤控件 label = tk.Label(root, text="請輸入含x的數學公式:", font=("微軟雅黑", 18), fg="blue") label.place(relx=0.2, rely=0.1) # 輸入框 entry = tk.Entry(root, font=("華文楷體", 15)) entry.place(relx=0.1, rely=0.2, relwidth=0.8) # 建立畫布區 btn_draw = tk.Button(root, text="建立", cursor="hand2", width=10, bg="orange", relief="raised", command=create ) btn_draw.place(relx=0.1, rely=0.3) # 繪圖按鈕 btn_draw = tk.Button(root, text="繪圖", cursor="hand2", width=10, bg="green", relief="raised", command=plot_f ) btn_draw.place(relx=0.4, rely=0.3) # 清除按鈕 btn_clear = tk.Button(root, text="清除", cursor="hand2", width=10, bg="yellow", relief="raised", command=clear ) btn_clear.place(relx=0.7, rely=0.3)
3.figure.py
""" 畫布文件,實現繪圖區域的顯示,並返回畫布的對象。 """ import tkinter as tk # 建立畫布須要的庫 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # 建立工具欄須要的庫 from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk # 快捷鍵須要的庫 from matplotlib.backend_bases import key_press_handler # 導入畫圖經常使用的庫 from matplotlib.figure import Figure def plot_fun(root): """ 該函數實現的是內嵌畫布,不負責畫圖,返回畫布對象。 :param root:父親控件對象, 通常是容器控件或者窗體 :return: 畫布對象 """ # 畫布的大小和分別率 fig = Figure(dpi=100) axs = fig.add_subplot(111) # 建立畫布 canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea. canvas.draw() # 顯示畫布 canvas.get_tk_widget().pack() # 建立工具條 toolbar = NavigationToolbar2Tk(canvas, root) toolbar.update() # 顯示工具條 canvas.get_tk_widget().pack() # 調用快捷鍵 def on_key_press(event): key_press_handler(event, canvas, toolbar) canvas.mpl_connect("key_press_event", on_key_press) # 返回畫布的對象 return axs
4.plot.py
""" 繪圖文件,負責函數曲線的繪製 """ import numpy as np def plot_main(string, plt): """ 負責函數曲線的繪製 :param string: 數學表達式 :param plt: 畫布的對象 :return: 無 """ list_expr = [] list_expr = string.split(",") string1 = [] for sub_expr in list_expr: string1.append(sub_expr) x = np.linspace(-10, 10, 100) y = [] num = string.count('x') for i in x: t = (i, ) * num string = string.replace("x", "(%f)") i = eval(string % t) y.append(i) plt.plot(x, y) plt.grid(True) plt.legend(labels=string1)
(四)文件結構
四個文件均處於同一個文件夾下,用main.py來運行。
(五)項目下載:
百度網盤下載
連接:https://pan.baidu.com/s/13G_hWqagxqHRkdHaYcxiQQ 提取碼:codq