PyQt5和matplotlib等绘图库制作一个数据可视化工具


目录

  • 一、使用环境
    • 1.QtCreator 4.8.0
    • 2.PyCharm
    • 3.Python环境--Python 3.7
  • 二、UI界面
    • 2.1 设计UI界面
      • 2.1.1 项目创建
      • 2.1.2 界面设计
    • 2.2 使用QSS对界面进行美化
    • 2.3 将UI界面转换为.py文件
  • 三、项目框架
    • 3.1 ui_MainWindow.py------UI界面转.py文件
    • 3.2 res_re.py------资源文件
    • 3.3 myFigureCanvas.py------自定义绘图组件类
    • 3.4 myMainWindow.py------功能实现
    • 3.5 DataVisualizationTool.py------主程序生成
  • 四、项目打包
  • 五、使用方式
  • 六、项目源码
  • 七、参考资料
  • 后记


首先来几张图展示一下界面。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第1张图片
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第2张图片
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第3张图片
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第4张图片
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第5张图片
最后附一个动图来演示一下效果:

PyQt5和matplotlib等绘图库制作一个数据可视化工具_第6张图片
是不是感觉还不错,接下来我们就来看看做这么一个小工具的过程吧。


一、使用环境

1.QtCreator 4.8.0

使用Qt进行界面创作的理由是它可以很方便的生成UI界面,并且制作UI界面的过程不需要任何代码的编写,这对于想要快速制作一个界面的人来说,Qt在这方面算是个不错的优点。

首先是Qt的安装。

Qt的安装很方便,在其官网上下载便可。

Qt官网地址:Qt官网.

2.PyCharm

Python的IDE有很多,我个人喜欢PyCharm,它的代码提示与补全功能在开发任何项目里都有很大的价值。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第7张图片

3.Python环境–Python 3.7

Python 3.7的环境已经用了很多年,个人认为比较稳定。

二、UI界面

2.1 设计UI界面

安装好Qt以后,我们就可以进行UI界面的制作了。在制作的过程中不需要编写任何代码,只需要使用Qt本身自带的组件库就可以完成基本的UI界面了,这对于不熟悉Qt的人来说是一件好事。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第8张图片

2.1.1 项目创建

打开Qt Creator后,点击“新建文件或项目”,选择默认的“Application”–“Qt Widgets Application”即可,之后自定义项目名称和路径,接下来一路按照默认点击“下一步”即可。

PyQt5和matplotlib等绘图库制作一个数据可视化工具_第9张图片
创建项目后具体的结构如图所示:
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第10张图片
其中Resources为资源文件,其中包括之后界面设计用到的图标,logo等图片文件,Resources的创建方法为:右键项目名称,点击“Add New…”,选择“Qt”–“Qt Resources Files”即可完成Resources的创建。

2.1.2 界面设计

在项目列表中点击“Forms”—”MainWindow.ui“后,便出现了如图所示的设计界面,然后便根据情况,通过拖拽左侧的组件设计自己需要的界面。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第11张图片
在拖拽组件后,在右侧有相关组件的属性,根据实际情况修改属性,而在其中,修改组件的名称至关重要,因为在之后使用Python代码编写具体功能时需要使用组件的名称。

2.2 使用QSS对界面进行美化

和CSS类似,Qt有着自己的界面优化方案。Qt样式表(Qt Style Sheets,QSS)是用于定制用户界面的强有力的机制,其概念、术语是受到HTML中的级联样式表(Cascading Style Sheets,CSS)启发而来。而在该界面的制作中,我选择了直接在每个组件内加入QSS,但这耗费的一定的时间。

修改QSS的方法为:右键单击你想要修改的组件,选择”改变样式表“,在弹出的文本框中加入QSS,即可完成界面的美化。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第12张图片

2.3 将UI界面转换为.py文件

在将在Qt制作的UI文件之后,就是将其转换为.py文件,在操作之前需要安装PyQt5,而安装PyQt5的方法很简单,在PyPI网站上有最新的版本,直接使用pip安装即可:

pip3 install PyQt5

直接连接PyPI服务器可能速度比较慢,我们可以使用清华大学的镜像网站:

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5

使用PyQt5的两个可执行程序进行转换,分别是:pyuic5.exe和pyrcc5.exe。

  • pyuic5.exe是用于将Qt Designer(或Qt Creator内置的UI Designer)可视化设计的界面文件(.ui文件)编译转换为Python程序文件的根据软件,是使用PyQt5设计GUI程序最常使用的根据软件
  • pyrcc5.exe是用于将Qt Creator里设计的资源文件(.qrc文件)编译转换为Python程序文件的工具软件,资源一般存储了图标、图片等UI设计资源。

这两个工具软件使用起来也很方便,Win+R打开控制台后首先使用cd跳转到UI文件的地址,然后使用pyuic5和pyrcc5即可。

例如:假设文件HelloWorld.ui保存在目录“C:\admin\UI”,执行下面的指令即可完成转换:

cd C:\admin\UI
pyuic5 -o ui_HelloWorld.py HelloWorld.ui

同理,将资源文件转换为Python文件的方法如下所示:

cd C:\admin\UI
pyrcc5 res.qrc -o HelloWorld.ui

而为了节约时间,方便操作,我们可以建立一个批处理文件app.bat。你只要双击该文件便可以快速将UI文件和资源文件转换为Python文件。例如:假设你所建立的Qt项目名称为“QtApp”,所在路径为“C:\admin”,那么你就可以在该路径下新建一个批处理文件,文件内容如下:

echo off

rem将子目录QtApp下的UI文件复制到当前目录下
copy .\QtApp\HelloWorld.ui HelloWorld.ui

rem用pyuic5编译UI文件
pyrcc5 res.qrc -o HelloWorld.ui

rem用pyrcc5编译UI文件
pyrcc5 .\QtApp\res.qrc -o HelloWorld.ui

在进行如上所示的操作后,同时生产了UI文件和资源文件,这时你就可以在目录中看到编译完成后的Python文件了。

三、项目框架

3.1 ui_MainWindow.py------UI界面转.py文件

UI文件编译后的内容是一个类,如下所示:
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第13张图片
pyuic5通过编译,实际上创建了一个叫做Ui_MainWindow的类,在这个类里包含了UI文件中各个组件的相关属性,以及涉及的资源文件等。

3.2 res_re.py------资源文件

打开编译后的资源文件后,查看它的内容,你会发现文件的内容如图所示:
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第14张图片
编译完成后的资源文件里保存的是相关图片的十六进制编码数据,还有相关的管理代码。

3.3 myFigureCanvas.py------自定义绘图组件类

我们在设计这个UI的时候,是使用matplotlib等绘图库的,为了方便设计,设计一个从QWidget继承的绘图组件类QmyFigureCanvas,在这个类里创建一个FigureCanvas对象、一个Figure对象和一个NavigationToolBar工具栏,构成一个绘图组件。在进行界面设计的时候,我们只要将放置的QWidget组件提升为QmyFigureCanvas类,就可以完成可视化的展示,其完整代码如下所示:

from PyQt5.QtWidgets import  QWidget

import matplotlib as mpl

from  matplotlib.backends.backend_qt5agg import (FigureCanvas,
            NavigationToolbar2QT as NavigationToolbar)

from PyQt5.QtWidgets import   QVBoxLayout

import matplotlib.pyplot as plt

class QmyFigureCanvas(QWidget):
   
   def __init__(self, parent=None, toolbarVisible=True,showHint=False):
      super().__init__(parent) 

      self.figure=plt.figure()  #公共的figure属性
      figCanvas = FigureCanvas(self.figure)  #创建FigureCanvas对象,必须传递一个Figure对象

      self.naviBar=NavigationToolbar(figCanvas, self)  #公共属性naviBar
      self.__changeActionLanguage()    #改为汉语

      actList=self.naviBar.actions()   #关联的Action列表
      count=len(actList)         #Action的个数
      self.__lastActtionHint=actList[count-1]   #最后一个Action,坐标提示标签
      self.__showHint=showHint   #是否在工具栏上显示坐标提示
      self.__lastActtionHint.setVisible(self.__showHint)    #隐藏其原有的坐标提示
      
      self.__showToolbar=toolbarVisible  #是否显示工具栏
      self.naviBar.setVisible(self.__showToolbar)
      
      layout = QVBoxLayout(self)
      layout.addWidget(self.naviBar)   #添加工具栏
      layout.addWidget(figCanvas)      #添加FigureCanvas对象
      layout.setContentsMargins(0,0,0,0) 
      layout.setSpacing(0) 

      #鼠标滚轮缩放
      self.__cid=figCanvas.mpl_connect("scroll_event",self.do_scrollZoom)

##=====公共接口函数
   def setToolbarVisible(self,isVisible=True): ##是否显示工具栏
      self.__showToolbar=isVisible
      self.naviBar.setVisible(isVisible)

   def setDataHintVisible(self,isVisible=True): ##是否显示工具栏最后的坐标提示标签
      self.__showHint=isVisible
      self.__lastActtionHint.setVisible(isVisible) 
      
   def redraw(self): ##重绘曲线,快捷调用
      self.figure.canvas.draw()
   
   def __changeActionLanguage(self):   ##汉化工具栏
      actList=self.naviBar.actions()    #关联的Action列表
      actList[0].setText("复位")         #Home
      actList[0].setToolTip("复位到原始视图")    #Reset original view
      
      actList[1].setText("回退")         #Back
      actList[1].setToolTip("回退前一视图")      #Back to previous view
      
      actList[2].setText("前进")         #Forward
      actList[2].setToolTip("前进到下一视图")    #Forward to next view

      actList[4].setText("平动")         #Pan
      actList[4].setToolTip("左键平移坐标轴,右键缩放坐标轴")  #Pan axes with left mouse, zoom with right
      
      actList[5].setText("缩放")         #Zoom
      actList[5].setToolTip("框选矩形框缩放")     #Zoom to rectangle

      actList[6].setText("子图")         #Subplots
      actList[6].setToolTip("设置子图")          #Configure subplots
      
      actList[7].setText("定制")         #Customize
      actList[7].setToolTip("定制图表参数")      #Edit axis, curve and image parameters

      actList[9].setText("保存")         #Save
      actList[9].setToolTip("保存图表")          #Save the figure
      

   def do_scrollZoom(self,event): #通过鼠标滚轮缩放
      ax=event.inaxes   # 产生事件axes对象
      if ax==None:
         return
      
      self.naviBar.push_current() #Push the current view limits and position onto the stack,这样才可以还原
      xmin,xmax=ax.get_xbound()
      xlen=xmax-xmin
      ymin,ymax=ax.get_ybound()
      ylen=ymax-ymin

      xchg=event.step*xlen/20  #step [scalar],positive = ’up’, negative ='down'
      xmin=xmin+xchg
      xmax=xmax-xchg
      ychg=event.step*ylen/20
      ymin=ymin+ychg
      ymax=ymax-ychg

      ax.set_xbound(xmin,xmax)
      ax.set_ybound(ymin,ymax)
      event.canvas.draw()

而将QWidget提升为QmyFigureCanvas的方法也很简单,在该项目里,我们进行可视化展示的界面组件为QWidget,将该组件拖拽到需要的位置,将这个组件提升为QmyFigureCanvas类,头文件为myFigureCanvas,提升组件的对话框如下图所示。
PyQt5和matplotlib等绘图库制作一个数据可视化工具_第15张图片

3.4 myMainWindow.py------功能实现

该文件也是一个基于QMainWindow的出口类QmyMainWindow,它包含了众多定义的函数,而这些函数就是最终进行可视化的实现。

完成后的可视化工具有五大类多大20+的不同可视化结果,在这里我们使用matplotlib中最常用的plot()函数来举例,它所绘制出的结果为折线图。

首先我们在该类中定义一个基本的绘图功能__drawPlot( ),它将给定的数据绘制在之前提升的QmyFigureCanvas的QWidget组件中。该函数如下所示:

def __drawPlot(self,x=[1,2,3,4,5],y=[2,3,5,6,9],title='Plot',
                             leg='Line-Plot',xlabel='Xlabel',
                             ylabel='Ylabel',style='fast',loc='best',
                             titlefontsize=14,titlecolor='black',
                             axisfontsize=14,axisfontcolor='black',bgcolor='white',
                             linestyle='-',linewidth=2,
                             linecolor='steelblue',alpha=0.8):
      self.ui.widgetPlot.figure.clear()
      mpl.style.use(style)
      mpl.rcParams['font.sans-serif']=['simhei']
      mpl.rcParams['font.size']=9         #显示汉字
      mpl.rcParams['axes.unicode_minus'] =False    #减号unicode编码
      ax1=self.ui.widgetPlot.figure.add_subplot(111,facecolor=bgcolor)
      ax1.set_title(title,fontsize=titlefontsize,color=titlecolor)
      ax1.plot(x,y,label=leg,ls=linestyle,lw=linewidth,c=linecolor,alpha=alpha)
      ax1.set_xlabel(xlabel,fontsize=axisfontsize,color=axisfontcolor)
      ax1.set_ylabel(ylabel,fontsize=axisfontsize,color=axisfontcolor)
      ax1.legend(loc='upper left')

而另一个函数为当点击绘制函数时,该函数将其他组件获取的参数和数据进行重新绘制,在这个过程中会调用上面的__drawPlot()函数。这个函数的命名也有讲究,函数命名格式为“on_XXX_clicked”,其中“XXX”为QPushButton组件的名称。该函数代码如下所示:

@pyqtSlot()   #重画折线图表
def on_redraw_plot_clicked(self):
      try:
         self.ui.statusBar.clearMessage()
         xdata=self.ui.x_data.text().split()
         ydata=[float(y) for y in self.ui.y_data.text().split()]
         xlab=self.ui.editXtitle.text()    #获取X轴标题
         ylab=self.ui.editYtitle.text()    #获取Y轴标题
         totaltitle=self.ui.edittitle.text()    #获取图表标题
         plotstyle=self.ui.comboBox_style.currentText()    #获取绘图风格
         plotlabel=self.ui.editlegendname.text()    #获取图例名称
         titlefontsize=self.ui.spinbox_titlefontsize.value()    #获取标题字体大小
         axisfontsize=self.ui.spinbox_titlefontsize.value()    #获取坐标轴字体大小
         titlefontcolor=self.ui.comboBox_titlefontcolor.currentText()    #获取标题文字颜色
         axisfontcolor=self.ui.comboBox_axisfontcolor.currentText()    #获取坐标轴文字颜色
         plotbgcolor=self.ui.comboBox_plotbgcolor.currentText()    #获取图表背景颜色
         #获取线条类型
         linestyle='-'
         or_linestyle=self.ui.comboBox_plotlinetype.currentText()
         if or_linestyle=='实线':
            linestyle='-'
         elif or_linestyle=='破折线':
            linestyle='--'
         elif or_linestyle=='点划线':
            linestyle='-.'
         elif or_linestyle=='虚线':
            linestyle=':'
         else:
            linestyle=""
         #获取线宽
         linewidth=self.ui.doubleSpinBox_plotlw.value()
         #获取线条颜色
         linecolor=self.ui.comboBox_plotlinecolor.currentText()
         #获取透明度
         alpha=self.ui.doubleSpinBox_plotalpha.value()
         #获取图例位置
         loc=self.ui.comboBox_loc.currentText()
         self.__drawPlot(x=xdata,y=ydata,xlabel=xlab,ylabel=ylab,title=totaltitle,
                                       style=plotstyle,leg=plotlabel,bgcolor=plotbgcolor,
                                       titlefontsize=titlefontsize,axisfontsize=axisfontsize,
                                       titlecolor=titlefontcolor,axisfontcolor=axisfontcolor,
                                       linestyle=linestyle,linewidth=linewidth,
                                       linecolor=linecolor,alpha=alpha,loc=loc)
         self.ui.widgetPlot.redraw()
         self.ui.statusBar.showMessage('折线图绘制成功!')
      except:
         self.ui.statusBar.clearMessage()
         self.ui.statusBar.showMessage('绘制失败!请检查是否操作正确!')

其他可视化结果的函数同理。

3.5 DataVisualizationTool.py------主程序生成

该函数为项目的GUI程序入口,运行此Python文件便可以生成可视化窗口。具体代码如下所示:

# -*- coding:GBK -*-

##  GUI应用程序主程序入口

import sys

from PyQt5.QtWidgets import  QApplication

from myMainWindow import QmyMainWindow
    
app = QApplication(sys.argv)    #创建GUI应用程序
##icon = QIcon(":/icons/images/app.ico")
##app.setWindowIcon(icon)

mainform=QmyMainWindow()        #创建主窗体
mainform.show()                 #显示主窗体

sys.exit(app.exec_()) 

四、项目打包

Python程序打包我们使用最常用的pyinstaller即可,在Windows里使用Win+R进入到控制台,使用cd进入到DataVisualizationTool.py文件所在的目录,然后使用如下命令即可:

pyinstaller DataVisualizationTool.py --noconsole --icon="logo.ico"

其中“–noconsole”表示项目打开的时候不会出现控制台,而–icon=“logo.ico”标识给打包生成的软件添加的Logo,并且注意这里的图片文件必须是ico格式,不能是png等图片文件。

另外一点,在项目主程序里涉及到文件的读写,为了程序的正常运行,记得把所用到的文件复制到打包的文件中。

五、使用方式

该项目的UI界面结构很简单,左侧是操作区,右侧是显示区,下方还有一个状态栏用来显示绘图是否成功。

左侧的状态栏里的功能很明显,在数据栏中输入数据,然后在下方调整相关属性,最后点击绘图按钮,便可以在右侧的显示区展示可视化结果了。

值得一提的是,输入的数据必须以空格分隔,个别的数据是二维数据,数据间以逗号(英文输入法)分隔,数组间以空格分隔,比如热力图。

六、项目源码

百度网盘链接: DataVisualizationTool.
提取码:kymd

七、参考资料

  1. 参考书《Python Qt GUI与数据可视化编程》。
    PyQt5和matplotlib等绘图库制作一个数据可视化工具_第16张图片
  2. matplotlib官方网站:https://matplotlib.org/gallery/index.html.
    PyQt5和matplotlib等绘图库制作一个数据可视化工具_第17张图片
  3. pyecharts文档:Pyecharts官网.

后记

在做这个项目的过程中,其实还使用了pyecharts进行绘图,当然你也可以将Python的其他绘图库嵌入其中,实现起来也并不难。

《Python Qt GUI与数据可视化编程》这本书对我有很大的帮助,对于想学习Python+Qt的爱好者来说是很有价值的,推荐一看。

你可能感兴趣的:(数据可视化,python,qt,pyqt)