tkinter內嵌Matplotlib系列(二)之函數曲線繪製

目錄

[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)框架圖解:

01.png

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來運行。

02.png

(五)項目下載:

百度網盤下載

連接:https://pan.baidu.com/s/13G_hWqagxqHRkdHaYcxiQQ 提取碼:codq

做者:Mark

日期:2019/02/15 週五

相關文章
相關標籤/搜索