上一例,我们学习了基本的绘图及显示方法,下面来点稍微复杂的应用,导入一个xml文档,将其中的数据进行图表输出。
前面的步骤请看之前的文章,这里不再赘述。只是在QT设计时我们用如下的界面。
widget控件用来显示饼图
lineEdit控件用来显示路径。
三个按钮控件分别是输入文件,显示图形,清除图形。
怎么生成UI详细不赘述了,参照前面一例。生成按钮事件。关键在于XML导入,我使用的XML是从统计局下载的。结构入下图:
导入XML库
import xml.dom.minidom
我贴上源代码。这是Matplotlibwidget.py文件的。
import sys
import matplotlib
matplotlib.use("Qt5Agg")
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from PyQt5.QtCore import QTimer
import random
import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
import xml.dom.minidom #导入XML库
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
plt.rcParams['font.sans-serif']=['simhei'] #这里是matplotlib支持中文标签的方法
plt.rcParams['axes.unicode_minus']=False #解决负号显示错误的问题
self.fig = plt.Figure(figsize=(width, height), dpi=dpi)
self.axes = self.fig.add_subplot(111)
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class Matplotlibwidget(QWidget):
def __init__(self, parent=None):
super(Matplotlibwidget, self).__init__(parent)
self.initUi()
def initUi(self):
self.layout = QVBoxLayout(self)
self.mpl = MyMplCanvas(self, width=15, height=15, dpi=100)
self.mpl.axes.axis('off') #默认不显示坐标轴
self.mpl.axes.set_title(u'各国新生儿死亡率统计2015') #输出默认的题目
self.layout.addWidget(self.mpl)
def inputfile(self):
global filename #声明全局变量,以便其他函数调用
filename1, filetype=QFileDialog.getOpenFileName(self, "chooseFiles")
#调用Pyqt默认的文件对话框,获得选择的文件名和类型
filename=filename1 #将获得的文件名传递给全局变量
return filename1 #函数返回文件名
def plot(self):
dom1=xml.dom.minidom.parse(filename) #从全局变量里获取文件路径
root=dom1.documentElement #获取XML文档的元素
itemlist=root.getElementsByTagName('field') #获取 field 标签里的全部元素
dbtime=itemlist[0].childNodes[0].nodeValue #获取第一个field里的内容也就是 2015年
dbtype=itemlist[1].childNodes[0].nodeValue #获取第二个field里的内容也就是 婴儿死亡率
dbzone=itemlist[2].childNodes[0].nodeValue #获取第三个field里的内容也就是 阿富汗
dbdata=itemlist[3].childNodes[0].nodeValue #获取第四个field里的内容也就是 66.30
ddata=int(float(dbdata)) #将66.30转化为整型
dtitle=str(dbtime+dbzone+dbtype) #组一个字符串
labels='婴儿死亡率', '婴儿存活率' #设置饼图的标签 顺序需要和之后的sizes对应
sizes=[ddata, 100-ddata] #设置饼图的占比数值,加起来要是100。换句话说百分比要算出来。
explodes=(0.1, 0) #饼图每个扇区的偏离值,越大离中心越远。
self.mpl.axes.set_title(dtitle) #设置标题
self.mpl.axes.pie(sizes, explode=explodes, labels=labels,autopct='%1.1f%%', shadow=True, startangle=90) #画饼图,(占比数值,偏离值,标签)是最常用的。其他的还有阴影啊,起始角度什么的看着设置就行。
self.mpl.draw() #开始画图
def clear_plot(self):
self.mpl.axes.cla() #清除图形
self.mpl.axes.axis('off') #不显示坐标轴
self.mpl.draw() #绘图
为了显示的清楚,有地儿写注释,我没有使用循环来获取XML数据,在工作中应该使用循环来得到全部的数据列表。
之后编写事件 people.py,之前一例已经细说。这里没什么特别的。
# -*- coding: utf-8 -*-
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow
from Ui_people import Ui_MainWindow
global filename
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
@pyqtSlot()
def on_startButton_clicked(self):
self.widget.plot()
@pyqtSlot()
def on_clearButton_clicked(self):
self.widget.clear_plot()
@pyqtSlot()
def on_inputButton_clicked(self):
global filename
filename=self.widget.inputfile()
self.lineEdit.setText(filename)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app= QApplication(sys.argv)
MainWindow=MainWindow()
MainWindow.show()
sys.exit(app.exec_())
运行结果:
点击input输入文件
点击start开始从XML文件中获取数据并绘图。