zoukankan      html  css  js  c++  java
  • Python利用Matplotlib和Tkinter在应用程序中内嵌图表

    在日常应用程序开发中,图表(折线图,柱状图等)以其直观显示,清晰明了的优势,使得应用范围越来越广泛,本文以一个简单的小例子,简述如何将Tkinter和Matplotlib相互关联起来,在应用程序中嵌入图表,仅供学习分享使用,如有不足之处,还请指正。

    涉及知识点

    1. Tkinter 是Python内置的桌面程序开发组件库,包含日常使用的基础组件(如:Label,Button,Entry等),利用Tkinter可以方便的开发可视化程序。
    2. Matlotlib 是一个开源的数据可视化类库,利用matplotlib可以绘制各种类型的图表(如:折线图,柱状图,散点图等)。
    3. Numpy 是一个开源的数学相关的类库,广泛应用于数学计算等领域。本例主要使用Numpy提供的数学函数和随机数生成数据源。

    操作步骤

    如果要将matplotlib生成图表和Tkinter生成的GUI程序关联起来,需要以下3个步骤:

    1. 创建Matplotlib的figure(画布)对象,并在figure上进行绘图。
    2. 创建FigureCanvasTkAgg(画布容器)对象,参数为第1步生成的figure对象和容器存放的父对象,并调用创建对象的draw函数。
    3. 调用FigureCanvasTkAgg对应组件的Pack方法,将对象显示在页面上。

    示例效果图

    将Matlotlib生成的曲线图,嵌入到普通的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)  # 设置网格
    View Code

    创建图表容器,并显示代码

     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)方法对图片进行切分。如下所示:

     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的图表形式还有很多,本例只是抛砖引玉,简述两种图表的生成方式,其他的图表则不做赘述。

    如需源码链接,可点击链接下载。一首小词,舒缓一下心情。

    浣溪沙·堤上游人逐画船

    宋代:欧阳修

    堤上游人逐画船,拍堤春水四垂天。绿杨楼外出秋千。
    白发戴花君莫笑,六幺催拍盏频传。人生何处似樽前!
  • 相关阅读:
    form组件进阶_django
    form组件_django
    django的数据库ORM进阶操作
    内网安装python模块_python
    Redhat7.4安装oracle11.2.0.4版本数据库遇见的问题_oracle
    Redis基础数据类型与对象
    SpringIOC容器——ApplicationContext和BeanFactory
    AQS源码解析
    Java内存模型(一)
    面试准备笔记
  • 原文地址:https://www.cnblogs.com/hsiang/p/13463999.html
Copyright © 2011-2022 走看看