一般的書上介紹Matplotlib的繪圖功能都主要是介紹matplotlib.pyplot模塊中的指令式繪圖功能,因?yàn)檫@種方式與MATLAB很相似,使用過(guò)MATLAB的人轉(zhuǎn)而使用Matplotlib繪圖會(huì)比較容易上手。但是這種方式將繪圖的效果都固定在程序里了,例如曲線的顏色、線條類型等,如果要修改就需要修改源程序重新運(yùn)行,所以這種方式只適合做研究時(shí)的快速數(shù)據(jù)可視化,不能做成GUI應(yīng)用程序進(jìn)行交互式繪圖。
Matplotlib是完全采用面向?qū)ο蠓椒ㄔO(shè)計(jì)的,圖的各個(gè)組成元素,如圖、子圖、坐標(biāo)軸、曲線等都有相應(yīng)的類,還有各種涉及圖的操作的類。通過(guò)類的接口函數(shù)和屬性可以對(duì)圖的各個(gè)組成元素進(jìn)行完全的控制,這種方法稱為面向?qū)ο螅∣bject-Oriented,OO)方法。面向?qū)ο蠓椒ㄟm合在GUI應(yīng)用程序中使用,因?yàn)樵诔绦蛑锌梢詫?duì)這些對(duì)象實(shí)例進(jìn)行操作。
下面先用一個(gè)簡(jiǎn)單的程序演示在GUI應(yīng)用程序中使用Matplotlib的面向?qū)ο蠓椒ɡL圖的基本方法。示例Demo14_1目錄下的文件Demo14_1GUI.py的完整代碼如下:
## 程序文件: Demo14_1GUI.py ## 使用matplotlib 面向?qū)ο蠓椒ㄔ贕UI中繪圖 import sys import numpy as np import matplotlib as mpl from matplotlib.backends.backend_qt5agg import (FigureCanvas, NavigationToolbar2QT as NavigationToolbar) from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtCore import Qt class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #調(diào)用父類構(gòu)造函數(shù) self.setWindowTitle("Demo14_1, GUI中的matplotlib繪圖") ## rcParams[]參數(shù)設(shè)置,以正確顯示漢字 mpl.rcParams['font.sans-serif']=['KaiTi','SimHei'] #漢字字體 mpl.rcParams['font.size']=12 #字體大小 mpl.rcParams['axes.unicode_minus']=False #正常顯示負(fù)號(hào) self.__iniFigure() #創(chuàng)建繪圖系統(tǒng),初始化窗口 self.__drawFigure() #繪圖 ##==========自定義函數(shù)=================def __iniFigure(self): ##創(chuàng)建繪圖系統(tǒng),初始化窗口 self.__fig=mpl.figure.Figure(figsize=(8, 5)) #單位英寸 self.__fig.suptitle("plot in GUI application") #總的圖標(biāo)題 figCanvas=FigureCanvas(self.__fig) #創(chuàng)建FigureCanvas對(duì)象 naviToolbar=NavigationToolbar(figCanvas, self) #創(chuàng)建工具欄 naviToolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.addToolBar(naviToolbar) #添加工具欄到主窗口 self.setCentralWidget(figCanvas) def __drawFigure(self): ##繪圖 t=np.linspace(0, 10, 40) y1=np.sin(t) y2=np.cos(2*t) ax1=self.__fig.add_subplot(1,2,1) #matplotlib.axes.Axes 類 ax1.plot(t,y1,'r-o',label="sin", linewidth=1, markersize=5) ax1.plot(t,y2,'b:',label="cos",linewidth=2) ax1.set_xlabel('X 軸') #x軸標(biāo)題 ax1.set_ylabel('Y 軸',fontsize=14) #y軸標(biāo)題 ax1.set_xlim([0,10]) ax1.set_ylim([-1.5,1.5]) ax1.set_title("曲線") #子圖標(biāo)題 ax1.legend() #自動(dòng)創(chuàng)建圖例 ax2=self.__fig.add_subplot(1,2,2) #matplotlib.axes.Axes 類 week=["Mon","Tue","Wed","Thur","Fri","Sat","Sun"] sales=np.random.randint(200,400,7) ax2.bar(week,sales) #繪制柱狀圖 ax2.set_xlabel('week days') #x軸標(biāo)題 ax2.set_ylabel('參觀人數(shù)') #y軸標(biāo)題 ax2.set_title("柱狀圖") #子圖標(biāo)題 ##============窗體測(cè)試程序================================if __name__=="__main__": app=QApplication(sys.argv) form=QmyMainWindow() form.show() sys.exit(app.exec_())
程序運(yùn)行時(shí)的界面如圖 14-2所示。注意這個(gè)程序是用PyQt5的GUI應(yīng)用程序框架創(chuàng)建的。為了減少程序的復(fù)雜度,沒(méi)有使用可視化方法設(shè)計(jì)UI窗體,而是采用純代碼的方式。程序中定義了一個(gè)基于QMainWindow的窗口類QmyMainWindow,界面構(gòu)造和繪圖都是在QmyMainWindow的構(gòu)造函數(shù)中實(shí)現(xiàn)的。
圖14-2 使用Matplotlib繪圖的PyQt5 GUI程序界面
Matplotlib的繪圖結(jié)果可以有各種輸出形式,例如在Python交互式環(huán)境中輸出繪圖結(jié)果,嵌入到wxpython、pygtk、Qt等GUI框架中輸出繪圖結(jié)果,將繪圖結(jié)果輸出為圖片文件,或在Web應(yīng)用程序中輸出繪圖結(jié)果。要實(shí)現(xiàn)這些不同的輸出,Matplotlib需要有不同的處理方法,這些不同的輸出功能就稱為后端(backend)。而相對(duì)的就是前端(frontend),是用戶面對(duì)的代碼。例如,對(duì)于一段相同的前端繪圖代碼,后端就是實(shí)現(xiàn)場(chǎng)景后面的工作以生成繪圖輸出。
有兩種后端,一種是用戶界面后端(也稱為交互式后端),例如用于wxpython、pygtk、tkinter、qt4、qt5、macosx的后端,另一種是用于生成圖片文件的后端,如生成PNG、SVG、PDF等文件。
對(duì)于用戶界面后端,Matplotlib還將渲染器(renderer)和畫布(canvas)分離開(kāi)來(lái),以實(shí)現(xiàn)更靈活的定制功能。Matplotlib使用的主要的渲染器是基于Anti-Grain Geometry C++庫(kù)的Agg渲染器。除了macosx,所有的用戶界面都使用Agg渲染器,因而有WXAgg、GTK3Agg、QT4Agg、QT5Agg、TkAgg等。有些用戶界面也支持其他的渲染器,如Cairo渲染器,因而有GTK3Cairo、QT4Cairo、QT5Cairo等。
在Matplotlib安裝目錄的“backends”子目錄里是這些后端的模塊文件,例如有backend_ gtk3agg.py、backend_gtk3cairo.py、backend_qt5agg.py、backend_qt5cairo.py等。本書只考慮QT5Agg渲染器,所以在程序的import部分有如下的語(yǔ)句:
from matplotlib.backends.backend_qt5agg import ( FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
這是從matplotlib.backends.backend_qt5agg模塊中導(dǎo)入了FigureCanvas類和NavigationToolbar2QT類,并將NavigationToolbar2QT類重命名為NavigationToolbar。
追蹤查看FigureCanvas類的源程序,可以發(fā)現(xiàn)它的上層父類之一是QWidget,所以,它是用于在PyQt5 GUI界面上顯示Matplotlib繪圖結(jié)果的Widget組件。要在PyQt5 GUI窗體上顯示Matplotlib繪圖結(jié)果,必須創(chuàng)建一個(gè)FigureCanvas界面組件,就如同使用PyQtChart模塊繪制圖表時(shí)需要先創(chuàng)建一個(gè)QChartView界面組件。
(1)為正常顯示漢字的設(shè)置
在自定義類QmyMainWindow的構(gòu)造函數(shù)里實(shí)現(xiàn)窗體界面構(gòu)造和Matplotlib繪圖。
首先對(duì)Matplotlib的全局設(shè)置做一些修改,以便正確顯示漢字。可以修改全局字典變量matplotlib.rcParams里的參數(shù),也可以修改配置文件matplotlibrc的內(nèi)容。程序中的設(shè)置語(yǔ)句如下:
mpl.rcParams['font.sans-serif']=['KaiTi','SimHei'] #漢字字體 mpl.rcParams['font.size']=12 #字體大小 mpl.rcParams['axes.unicode_minus']=False #正常顯示負(fù)號(hào)
第1行語(yǔ)句是設(shè)置字體族(font family)“sans-serif”的參數(shù),第3行語(yǔ)句是為了正常顯示負(fù)號(hào)。
Matplotlib中將字體分為5種字體族,分別是“serif”“sans-serif”“cursive”“fantasy”“monospace”,每一種字體族可以設(shè)定多種字體。在默認(rèn)的matplotlibrc文件中使用的字體族是“sans-serif”,這個(gè)字體族的字體不包含漢字字體,所以無(wú)法正常顯示漢字。
第1行語(yǔ)句將’font.sans-serif’參數(shù)設(shè)置為[‘KaiTi’, ‘SimHei’],Matplotlib將優(yōu)先使用字體’KaiTi’,如果找不到這個(gè)字體的字體文件,就使用后面的字體’SimHei’,可以為一個(gè)字體族設(shè)置多個(gè)字體。Windows系統(tǒng)中常見(jiàn)的漢字字體名稱如下。
關(guān)于字體的設(shè)置可以查看配置文件matplotlibrc的默認(rèn)內(nèi)容,在Matplotlib 3.0.0用戶手冊(cè)的第89頁(yè)。
(2)創(chuàng)建繪圖界面組件的函數(shù)__iniFigure()
構(gòu)造函數(shù)里調(diào)用自定義函數(shù)__iniFigure()創(chuàng)建繪圖相關(guān)的界面組件,此函數(shù)的完整代碼見(jiàn)前面的程序清單。程序首先創(chuàng)建了一個(gè)matplotlib.figure.Figure類對(duì)象self.__fig:
self.__fig=mpl.figure.Figure(figsize=(8, 5)) #單位英寸
Figure類就是用于繪圖的圖表類,是Matplotlib中一個(gè)主要的類,它負(fù)責(zé)管理一個(gè)圖形窗口中子圖、各種圖表組件的繪制,其功能類似于PyQtChart模塊中的QChart類。但是一個(gè)Figure里可以繪制多個(gè)子圖,而QChart只能繪制一個(gè)圖表。
創(chuàng)建FigureCanvas對(duì)象時(shí)必須傳遞一個(gè)Figure類對(duì)象,程序中是:
figCanvas=FigureCanvas(self.__fig) #創(chuàng)建FigureCanvas對(duì)象
這樣,F(xiàn)igure類對(duì)象self.__fig就用figCanvas作為圖形渲染區(qū)域(畫布),self.__fig的各種繪圖操作都在此畫布上顯示出來(lái)。
創(chuàng)建NavigationToolbar類導(dǎo)航工具欄naviToolbar時(shí)傳遞一個(gè)FigureCanvas對(duì)象作為參數(shù),即
naviToolbar=NavigationToolbar(figCanvas, self) #創(chuàng)建工具欄
這樣創(chuàng)建的導(dǎo)航工具欄的操作就是針對(duì)關(guān)聯(lián)的FigureCanvas類對(duì)象figCanvas。Navigation- Toolbar的父類是QToolBar,所以可以使用setToolButtonStyle()函數(shù)設(shè)置按鈕顯示方式,并且添加它作為主窗口的工具欄。
程序運(yùn)行時(shí),圖14-2中的工具欄與圖14-1中的工具欄有些差異,例如圖14-2的工具欄中有“Customize”按鈕對(duì)子圖進(jìn)行設(shè)置,而圖14-1的工具欄中沒(méi)有這個(gè)按鈕。兩個(gè)工具欄的“Subplots”按鈕彈出的對(duì)話框的界面也不同,這就是由于使用了不同的后端引起的。
FigureCanvas的父類是QWidget,所以其對(duì)象示例可以作為主窗口的中心組件。Navigation- Toolbar和FigureCanvas還有其他的一些功能,在后面再具體介紹。
(3)實(shí)現(xiàn)繪圖功能的函數(shù)__drawFigure()
構(gòu)造函數(shù)里調(diào)用自定義函數(shù)__drawFigure()繪圖,其完整代碼參見(jiàn)前面的代碼清單。
函數(shù)__drawFigure()實(shí)現(xiàn)的繪圖功能與程序Demo14_1Script.py中的幾乎相同,但是實(shí)現(xiàn)的方法不同。在文件Demo14_1GUI.py的import部分沒(méi)有導(dǎo)入matplotlib.pyplot,它完全使用面向?qū)ο蟮姆椒ɡL圖。
在使用NumPy的功能準(zhǔn)備好數(shù)據(jù)后,程序首先創(chuàng)建了一個(gè)子圖,代碼是:
ax1=self.__fig.add_subplot(1,2,1) #子圖1
self.__fig是matplotlib.figure.Figure類對(duì)象,是整個(gè)圖。使用Figure.add_subplot()函數(shù)創(chuàng)建了一個(gè)對(duì)象ax1。函數(shù)Figure.add_subplot()與matplotlib.pyplot.subplot()參數(shù)格式和功能完全相同,這里不再對(duì)參數(shù)做詳細(xì)的說(shuō)明,讀者可以通過(guò)內(nèi)建函數(shù)help()獲取該函數(shù)的詳細(xì)幫助信息,輸入指令是:
>>> from matplotlib.figure import Figure >>> help (Figure.add_subplot)
這里創(chuàng)建的對(duì)象ax1是matplotlib.figure.Axes類型,它是管理一個(gè)子圖區(qū)域繪圖的類。通過(guò)Axes類的接口函數(shù)在子圖區(qū)域畫圖,例如ax1使用plot()函數(shù)繪制了兩條曲線,Axes.plot()函數(shù)的使用方法與matplotlib.pyplot.plot()函數(shù)相同。
Axes類通過(guò)屬性和接口函數(shù)對(duì)子圖的各個(gè)組成元素,如曲線、坐標(biāo)軸范圍、標(biāo)題、網(wǎng)格線、圖例等進(jìn)行操作。一般通過(guò)一組set_和get_函數(shù)對(duì)一個(gè)屬性進(jìn)行設(shè)置和獲取,例如Axes.set_xlim()函數(shù)設(shè)置x軸坐標(biāo)范圍,Axes.get_xlim()函數(shù)返回x軸的坐標(biāo)范圍。這與matplotlib.pyplot模塊中的操作方法不同,pyplot.xlim()函數(shù)既可以設(shè)置x軸坐標(biāo)范圍,也可以返回x軸坐標(biāo)范圍。
Axes類是Matplotlib繪圖中最主要的一個(gè)類,一個(gè)子圖上的所有元素都由Axes管理,所以在GUI中進(jìn)行Matplotlib繪圖主要就是Axes類及其管理的各個(gè)子對(duì)象的操作,如坐標(biāo)軸(Axis類)、曲線(Line2D類)、文本(Text類)、圖例(Legend類)的操作。這些操作都使用面向?qū)ο蟮姆椒ǎcmatplotlib.pyplot中的指令式操作的方法不同,但實(shí)現(xiàn)的功能相同。
本節(jié)先通過(guò)一個(gè)簡(jiǎn)單示例演示了在GUI程序中使用Matplotlib繪圖的基本方法,下一節(jié)再對(duì)Matplotlib繪圖時(shí)常用到的各個(gè)類的使用方法進(jìn)行詳細(xì)介紹。
本文截選自《Python Qt GUI與數(shù)據(jù)可視化編程》
王維波,栗寶鵑,張曉東 著
本書介紹在Python中使用PyQt5和其他模塊進(jìn)行GUI和數(shù)據(jù)可視化編程的方法。第一部分介紹PyQt5設(shè)計(jì)GUI程序的基本框架,包括GUI應(yīng)用程序的基本結(jié)構(gòu)、窗體UI可視化設(shè)計(jì)與窗體業(yè)務(wù)邏輯的設(shè)計(jì)、信號(hào)與槽的特點(diǎn)和使用等。第二部分介紹GUI程序設(shè)計(jì)中一些主要功能模塊的使用,包括基本界面組件、事件處理、數(shù)據(jù)庫(kù)、繪圖、多媒體等。第三部分先介紹使用PyQtChart和PyQtDataVisualization進(jìn)行二維和三維數(shù)據(jù)可視化設(shè)計(jì)的方法,再介紹將Matplotlib嵌入PyQt5 GUI應(yīng)用程序窗口界面中進(jìn)行數(shù)據(jù)可視化的編程方法。通過(guò)研讀本書,讀者可以掌握使用PyQt5、PyQtChart、Matplotlib等模塊進(jìn)行GUI應(yīng)用程序和數(shù)據(jù)可視化設(shè)計(jì)的方法。
本書適合具有Python編程基礎(chǔ),并想通過(guò)Python設(shè)計(jì)GUI應(yīng)用程序或在GUI應(yīng)用程序中實(shí)現(xiàn)數(shù)據(jù)可視化的讀者閱讀和參考。
今天打開(kāi)電腦,系統(tǒng)彈出更新的提示,我點(diǎn)擊了一下,發(fā)現(xiàn)出錯(cuò)了,由于全部是英文,我英語(yǔ)又學(xué)得不好,沒(méi)看懂什么意思,如果有看懂的朋友待會(huì)可以在評(píng)論區(qū)幫忙給解釋一下,我先上圖吧。
看到了吧,就是這個(gè),反正大概意思就是說(shuō)可能是我硬件的問(wèn)題,不能升級(jí)安裝Windows11的版本,這個(gè)就有點(diǎn)棘手了,硬件不支持,應(yīng)該是不支持win11所需要的TPM功能模塊,不支持就不支持吧,總不能為了這個(gè)再換臺(tái)電腦,就得不償失了,畢竟現(xiàn)在這個(gè)電腦才用了4年不到,以現(xiàn)在的狀況來(lái)看再用個(gè)5年還是沒(méi)問(wèn)題的。
為什么這樣說(shuō)呢,由于我裝的是Windows10的工作站版,后來(lái)又開(kāi)通了預(yù)覽版的計(jì)劃安裝,所以,系統(tǒng)一直被推送著最新的系統(tǒng)測(cè)試版本,我感覺(jué)現(xiàn)在我這版應(yīng)該是絕版的win10專業(yè)版工作站版了,并且有很多的Windows11的元素在里面,但是整體跟Windows11的風(fēng)格又不太一樣,待會(huì)給大家上圖,大家看看就知到了。
這個(gè)是系統(tǒng)版本:Windows 10 專業(yè)工作站版,到這里就終止了,再也升級(jí)不了。
我們來(lái)看一下系統(tǒng)信息:
體驗(yàn)版本:Windows 10 Feature Experience Pack 321.13302.10.3,
時(shí)間:定格在了2021/?6/?8,
系統(tǒng)的版本號(hào)是:Dev,
操作系統(tǒng)的版本是:21390.2025
這個(gè)是系統(tǒng)圖標(biāo),是不是跟正常的Windows10不一樣,跟最新的Windows11也不一樣
這個(gè)是日歷,以前沒(méi)發(fā)現(xiàn)過(guò)日歷軟件,今天打開(kāi)發(fā)現(xiàn)這個(gè)還是很不錯(cuò)的,里面很詳細(xì),還能做標(biāo)記,不錯(cuò)。
這個(gè)是畫圖軟件的圖標(biāo),漂亮吧,不過(guò)打開(kāi)后倒是跟以前的畫圖功能一樣,界面也沒(méi)變化
這個(gè)是記事本軟件,圖標(biāo)換了,還是非常醒目的,打開(kāi)后跟畫圖一樣,與以前的版本沒(méi)有區(qū)別。
這個(gè)是右下角的任務(wù)欄里多了個(gè)天氣項(xiàng),有當(dāng)前室外溫度,空氣狀況等,打開(kāi)后顯示最新的時(shí)事新聞,還是不錯(cuò)的,不用打開(kāi)新聞網(wǎng)站就可以看新聞了。
這里就是系統(tǒng)的菜單,桌面,不知道大家發(fā)現(xiàn)沒(méi)有,這個(gè)狀態(tài)下可以看到當(dāng)前系統(tǒng)版本的一些基礎(chǔ)信息,你看到在哪里了嗎?
說(shuō)實(shí)話,這一版其實(shí)還是真的不錯(cuò)的,Windows11的前驅(qū)測(cè)試版,如果系統(tǒng)不壞的話會(huì)一直用下去吧,看能堅(jiān)持多久吧。
屏幕右下角,仔細(xì)看看,你會(huì)發(fā)現(xiàn)秘密所在。