@PyQt5記錄筆記之使用Matplotlib繪圖
1,要在PyQt5介面上顯示,首先要建立介面元件FigureCanvas,一個畫布(相當於用於顯示Matplotlib的Widget元件);
2,接著需要建立繪圖相關元件圖表類Figure,表示畫布上的整個圖,管理圖形視窗上的子圖以及各種圖表元件的繪製;
3,然後建立Axes子圖類繪製子圖,一個Figure上可以有多個子圖,一個子圖上所有元素都是由Axes管理,包括座標軸類(Axis),曲線類(Line2D),文字類(Text),圖例類等(Legend),當建立一個Axes物件時,會同時自動建立x軸y軸,對子圖上各個子物件進行操作。
例如:
axes = self.MainUI.widget.figure.add_subplot(1,1,1)#在已經建立的UI上建立一個子圖
axes.set_xlim(0,9)#x軸範圍
axes.set_xlabel(「distance[m]」)#橫座標標籤
axes.grid(b = True,which = ‘major’,axis = ‘both’)網格
t = []
s = []
for i in range(10):
t.append(i)
s.append(random.randint(0,1500))
axes.plot(t, s,picker=True)#畫曲線圖
axes.cla()#清除子圖內容
self.MainUI.widget.redraw()#對子圖執行完各種操作之後,及時重新整理
#self.figure.canvas.draw()
具體介面以及說明見:matplotlib.axes介面使用說明
建立NavigationToolbar工具列時,傳遞一個FigureCanvas物件作為引數,關聯FigureCanvas類物件。
naviBar = NavigationToolbar(figCanvas,self)#建立工具列
NavigationToolbar父類別是QToolbar,可以使用QToolbar的一些介面函數改造工具列。
事件名稱 | 觸發動作 |
---|---|
button_press_event | 滑鼠按鍵按下 |
button_release_event | 滑鼠按鍵釋放 |
motion_notify_event | 滑鼠移動 |
scroll_event | 滑鼠滾輪動作 |
key_press_event | 鍵盤按鍵按下 |
key_release_event | 鍵盤按鍵釋放 |
pick_event | 物件被拾取 |
figure_enter_event | 滑鼠進入一個Figure物件 |
figure_leave_event | 滑鼠離開一個Figure物件 |
axes_enter_event | 滑鼠進入一個子圖 |
axes_leave_event | 滑鼠離開一個子圖 |
滑鼠和鍵盤操作產生的事件,有如下屬性:
x,y:畫布上x,y的位置,單位畫素;
inaxes:產生滑鼠事件的Axes子圖物件;
xdata,ydata:滑鼠遊標處x,y的座標值
FigureCanvas類中,有兩個函數用來建立和解除事件與槽函數之間的關聯:
1,將事件與槽函數關聯mpl_connect(eventName,function),eventName型別為字串,為上述事件名稱,function為連線到的槽函數,返回一個編號,用來標誌此事件:
self.__cid = figCanvas.mpl_connect(「scroll_event」,self.do_scrollZoom)#支援滑鼠滾輪縮放
2,解除事件關聯mpl_disconnect(self.__cid)
下面程式碼自定義了一個QmyFigureCanvas類,繼承於QWidget類,作為一個繪圖元件,即在Qt Designer設計介面時,將一個QWidget元件提升為QmyFigureCanvas即可。
from PyQt5.QtWidgets import QWidget
from PyQt5 import QtCore
from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as FigureCanvas,NavigationToolbar2QT as NavigationToolbar)#使用者介面後端渲染,用來以繪圖的形式輸出
from PyQt5.QtWidgets import QVBoxLayout
from matplotlib.figure import Figure#圖表類
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy
class QmyFigureCanvas(QWidget):
mouseMove = QtCore.pyqtSignal(numpy.float64,mpl.lines.Line2D)#自定義觸發訊號,用於與UI互動
# mousePress = QtCore.pyqtSignal(numpy.float64,numpy.float64)
# mouseRelease = QtCore.pyqtSignal(numpy.float64,numpy.float64)
def __init__(self,parent=None,toolbarVisible=True,showHint=False):
super().__init__(parent)
# self.figure = mpl.figure.Figure()#公共屬性figure
self.figure = Figure()#公共屬性figur
figCanvas = FigureCanvas(self.figure)#建立FigureCanvas物件
self.naviBar = NavigationToolbar(figCanvas,self)#建立工具列
actList = self.naviBar.actions()
count = len(actList)
self.__lastActtionHint = actList[count-1]
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)#支援滑鼠滾輪縮放
self.__cid1 = figCanvas.mpl_connect("pick_event",self.do_series_pick)#支援曲線抓取
# self.__cid2 = figCanvas.mpl_connect("button_press_event",self.do_pressMouse)#支援滑鼠按下
self.__cid3 = figCanvas.mpl_connect("button_release_event",self.do_releaseMouse)#支援滑鼠釋放
self.__cid4 = figCanvas.mpl_connect("motion_notify_event",self.do_moveMouse)#支援滑鼠移動
self.mouseIsPress = False
self.pickStatus = False
#公共函數介面
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 do_scrollZoom(self,event):#通過滑鼠滾輪縮放
ax = event.inaxes #產生事件axes物件
if ax == None:
return
self.naviBar.push_current()
xmin,xmax = ax.get_xbound()
xlen = xmax - xmin
ymin,ymax = ax.get_ybound()
ylen = ymax - ymin
xchg = event.step * xlen / 20
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()
def do_series_pick(self,event):#picker事件獲取抓取曲線
self.series = event.artist
# index = event.ind[0]
# print("series",event.ind)
if isinstance(self.series,mpl.lines.Line2D):
self.pickStatus = True
def do_releaseMouse(self,event):#滑鼠釋放,釋放抓取曲線
if event.inaxes == None:
return
if self.pickStatus == True:
self.series.set_color(color = "black")
self.figure.canvas.draw()
self.pickStatus = False
# self.mouseRelease.emit(event.xdata,event.ydata)
def do_moveMouse(self,event):#滑鼠移動,重繪抓取曲線
if event.inaxes == None:
return
if self.pickStatus == True:
self.series.set_xdata([event.xdata,event.xdata])
self.series.set_color(color = "red")
self.figure.canvas.draw()
self.mouseMove.emit(event.xdata,self.series)#自定義觸發訊號,用於與UI互動
程式碼部分建立了一個包含工具列的Figure()圖表元件,並且自定義了滑鼠滾輪縮放事件,以及當滑鼠抓取直線後,進行直線在座標範圍內平移操作。
將自定義的QmyFigureCanvas應用於UI中,在UI中隨機繪製曲線,並新增axvline直線作為標誌線,可拖動標誌線進行其他操作顯示,如圖:
參考圖書:Python Qt GUI與資料視覺化程式設計