国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 詳解pyqt5的UI中嵌入matplotlib圖形并實時刷新(挖坑和填坑)

詳解pyqt5的UI中嵌入matplotlib圖形并實時刷新(挖坑和填坑)

2020-08-09 14:51wuwei_201 Python

這篇文章主要介紹了詳解pyqt5的UI中嵌入matplotlib圖形并實時刷新(挖坑和填坑),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、pyqt5的UI中嵌入matplotlib的方法

1、導(dǎo)入模塊

導(dǎo)入模塊比較簡單,首先聲明使用pyqt5,通過FigureCanvasQTAgg創(chuàng)建畫布,可以將畫布的圖像顯示到UI,相當(dāng)于pyqt5的一個控件,后面的繪圖就建立在這個畫布上,然后把這個畫布當(dāng)中pyqt5的控件添加到pyqt5的UI上,其次要導(dǎo)入matplotlib.figure的Figure ,這里要注意的是matplotlib.figure中的Figure,不是matplotlib.pyplot模塊中的Figure,要區(qū)分清楚。

?
1
2
3
4
5
6
import matplotlib
matplotlib.use("Qt5Agg") # 聲明使用pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg # pyqt5的畫布
import matplotlib.pyplot as plt
# matplotlib.figure 模塊提供了頂層的Artist(圖中的所有可見元素都是Artist的子類),它包含了所有的plot元素
from matplotlib.figure import Figure

2、創(chuàng)建pyqt5畫布,并簡單設(shè)置樣式

創(chuàng)建一個畫布類,繼承上面導(dǎo)入的FigureCanvasQTAgg,通過Figure 創(chuàng)建畫布,并且作為參數(shù)傳遞給父類FigureCanvasQTAgg(這里是關(guān)鍵一步!沒有這一步后面一切都是白費,不會添加成功!),最后一步添加繪圖區(qū)self.axes

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
  創(chuàng)建一個畫布類,并把畫布放到FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' # 設(shè)置窗體顏色
    plt.rcParams['axes.facecolor'] = 'b' # 設(shè)置繪圖區(qū)顏色
    self.width = width
    self.heigh = heigh
    self.dpi = dpi
    self.figs = Figure(figsize=(self.width, self.heigh), dpi=self.dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) # 在父類種激活self.fig, 否則不能顯示圖像
    self.axes = self.figs.add_subplot(111)

3、填上創(chuàng)建pyqt5畫布挖的坑

上面自定義的畫布類MyMatplotlibFigure寫的時候不會提示錯誤,但是當(dāng)你繪圖的時候會傻眼了,因為沒有報錯但是閃退了!!!然后逐個把可疑的類和方法try… except … print(er),希望python能告訴你原因,抱歉!最終結(jié)果是什么都沒有得到!使用debug單步調(diào)試慢慢分析,累死累活的一步一步看到最后添加畫布到pyqt5時,跳到一個模塊backend_qt5.py文件的第500行:if self.height() < 0 or self.width() < 0:從debug的變量分析中看到“(<class ‘TypeError'>, TypeError("‘int' object is not callable"), <traceback object at 0x000001C3E0397F08>)這是什么鬼?
其實這是一個很簡單的錯誤,但是不小心犯了排查起來很麻煩!!!錯誤的原因就是有些程序員在自定義類內(nèi)接收外部傳參時經(jīng)常把傳遞的參數(shù)轉(zhuǎn)換為全局變量,比如這個例子中初始化__init__方法接收的三個參數(shù) width、 heigh、 dpi,順手寫了個

?
1
2
3
self.width = width
self.heigh = heigh
self.dpi = dpi

 然后接著調(diào)用!問題就在這里了,其實不管你后面有沒有調(diào)用,都會閃退!!!!!為什么呢?
因為FigureCanvasQTAgg父類中導(dǎo)入了backend_qt5.py模塊,而backend_qt5模塊內(nèi)部也使用了相同的變量名self.width和self.heigh,所以呢,在這里用上面的寫法就造成了對父類變量的覆蓋。正確的寫法:

?
1
2
3
4
5
6
7
8
9
10
11
12
class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
  創(chuàng)建一個畫布類,并把畫布放到FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' # 設(shè)置窗體顏色
    plt.rcParams['axes.facecolor'] = 'b' # 設(shè)置繪圖區(qū)顏色
    # 創(chuàng)建一個Figure,該Figure為matplotlib下的Figure,不是matplotlib.pyplot下面的Figure
    # 這里還要注意,width, heigh可以直接調(diào)用參數(shù),不能用self.width、self.heigh作為變量獲取,因為self.width、self.heigh 在模塊中已經(jīng)FigureCanvasQTAgg模塊中使用,這里定義會造成覆蓋
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) # 在父類種激活self.fig, 否則不能顯示圖像(就是在畫板上放置畫布)
    self.axes = self.figs.add_subplot(111) # 添加繪圖區(qū)

這里直接使用傳參字符就可以了,這幾個參數(shù)后面用不到了,如果你能用到就隨便改個名字,比如self.w = width self.h = heigh

4、把畫布添加到pyqt5的UI中

這里就比較簡單了,創(chuàng)建一個簡單的窗口,添加label,實例化上面創(chuàng)建的自定義畫布類,用變量self.canvas接收實例,這就相當(dāng)于pyqt5的控件了,在label上創(chuàng)建布局,布局中添加畫布self.canvas
如果僅僅是把matplotlib的圖像添加到Ui中,plotcos這個繪圖方法放哪里都行,也可以在上面的自定義類中添加這個方法,只是最后繪圖的兩行簡單修改即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MainDialogImgBW_(QtWidgets.QMainWindow):
  """
  創(chuàng)建UI主窗口,使用畫板類繪圖。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("顯示matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)
 
  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.aexs.plot(t, s)
    self.canvas.figs.suptitle("sin") # 設(shè)置標(biāo)題

二、實時刷新matplotlib圖像的坑

實時刷新圖像如果通過網(wǎng)絡(luò)查詢,基本千篇一律的結(jié)果都是先clean清除之前的圖像、重新plot、加上重繪draw(),從其它帖子找了最具代表性的三部曲步驟如下:

?
1
2
3
self.axes.cla()
self.axes.plot(x, y, 'o',xx,yy)
self.draw()

 這三部曲是沒錯,但是只是他們說的有點簡單了,有些細(xì)節(jié)需要注意,否則一樣不會刷新或者報錯閃退。需要注意的坑是draw(),因為他們帖子上寫的簡單,實在不知道他們的self有幾個意思,一般情況下這么寫是錯的。**cla()清空了繪圖區(qū),plot()重新繪制了圖像,這兩個都是對繪圖區(qū)的操作,但是要draw()要重繪的是畫布層不是繪圖區(qū)。而且僅僅draw()是不夠的,還要flush_events()否則可能在刷新畫布過程中中途偶然閃退。**完整的正確代碼如下(上面的第4條例子大的寫法是繪圖方法在UI類內(nèi),下面的例子用另外一種寫法,在畫布類中創(chuàng)建繪圖方法):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
  創(chuàng)建一個畫布類,并把畫布放到FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    plt.rcParams['figure.facecolor'] = 'r' # 設(shè)置窗體顏色
    plt.rcParams['axes.facecolor'] = 'b' # 設(shè)置繪圖區(qū)顏色
    # 創(chuàng)建一個Figure,該Figure為matplotlib下的Figure,不是matplotlib.pyplot下面的Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) # 在父類種激活self.fig,
    self.axes = self.figs.add_subplot(111) # 添加繪圖區(qū)
  def mat_plot_drow_axes(self, t, s):
    """
    用清除畫布刷新的方法繪圖
    :return:
    """
    self.axes.cla() # 清除繪圖區(qū)
 
    self.axes.spines['top'].set_visible(False) # 頂邊界不可見
    self.axes.spines['right'].set_visible(False) # 右邊界不可見
    # 設(shè)置左、下邊界在(0,0)處相交
    # self.axes.spines['bottom'].set_position(('data', 0)) # 設(shè)置y軸線原點數(shù)據(jù)為 0
    self.axes.spines['left'].set_position(('data', 0)) # 設(shè)置x軸線原點數(shù)據(jù)為 0
    self.axes.plot(t, s, 'o-r', linewidth=0.5)
    self.figs.canvas.draw() # 這里注意是畫布重繪,self.figs.canvas
    self.figs.canvas.flush_events() # 畫布刷新self.figs.canvas
 
class MainDialogImgBW(QtWidgets.QMainWindow):
  """
  創(chuàng)建UI主窗口,使用畫板類繪圖。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("顯示matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)
 
  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.mat_plot_drow_axes(t, s)
    self.canvas.figs.suptitle("sin") # 設(shè)置標(biāo)題
 
 
if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())

**需要注意的地方就是畫布重繪的寫法,既不是self.draw()也不是self.axes.draw()或self.figs.draw(),而是self.figs.canvas.draw()和self.figs.canvas.flush_events(),這里比較坑的是寫這兩句代碼時沒有智能提醒!(我用的pycharm,也有可能是被這個坑了,不知道其他IDE是否會提醒)**這里還要提醒的是只有self.figs.canvas.draw()沒有self.figs.canvas.flush_events()時也會重繪,但是有可能在運行過程中閃退,所以還是加上比較安全。

三、實時更新matplotlib的另一種方法

上面是使用axes.cla()的方式刷新圖表,但是你有可能會遇到,你要展示的下一個圖形于前面一次圖表完全不同,包括畫布背景色等都不同,那么用上面的axes.cla()只清理繪圖區(qū)就不夠了,需要用得到清理畫布figure.clf(),這個地方你要看清楚,清理繪圖區(qū)方法是cla(),而清理畫布是clf()一字之差。另外一個需要注意的地方就是,清理畫布后之前畫布上的繪圖區(qū)axes也清理了,需要重新添加axes,完整代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class MyMatplotlibFigure(FigureCanvasQTAgg):
  """
  創(chuàng)建一個畫布類,并把畫布放到FigureCanvasQTAgg
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    # 創(chuàng)建一個Figure,該Figure為matplotlib下的Figure,不是matplotlib.pyplot下面的Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatplotlibFigure, self).__init__(self.figs) # 在父類種激活self.fig,
  def mat_plot_drow(self, t, s):
    """
    用清除畫布刷新的方法繪圖
    :return:
    """
    self.figs.clf() # 清理畫布,這里是clf()
    self.axes = self.figs.add_subplot(111) # 清理畫布后必須重新添加繪圖區(qū)
 self.axes.patch.set_facecolor("#01386a") # 設(shè)置ax區(qū)域背景顏色
    self.axes.patch.set_alpha(0.5) # 設(shè)置ax區(qū)域背景顏色透明度
    self.figs.patch.set_facecolor('#01386a') # 設(shè)置繪圖區(qū)域顏色
    self.axes.spines['bottom'].set_color('r') # 設(shè)置下邊界顏色
    self.axes.spines['top'].set_visible(False) # 頂邊界不可見
    self.axes.spines['right'].set_visible(False) # 右邊界不可見
    # 設(shè)置左、下邊界在(0,0)處相交
    # self.axes.spines['bottom'].set_position(('data', 0)) # 設(shè)置y軸線原點數(shù)據(jù)為 0
    self.axes.spines['left'].set_position(('data', 0)) # 設(shè)置x軸線原點數(shù)據(jù)為 0
    self.axes.plot(t, s, 'o-r', linewidth=0.5)
    self.figs.canvas.draw() # 這里注意是畫布重繪,self.figs.canvas
    self.figs.canvas.flush_events() # 畫布刷新self.figs.canvas
 
class MainDialogImgBW(QtWidgets.QMainWindow):
  """
  創(chuàng)建UI主窗口,使用畫板類繪圖。
  """
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("顯示matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatplotlibFigure(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)
 
  def plotcos(self):
    # plt.clf()
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.mat_plot_drow(t, s)
    self.canvas.figs.suptitle("sin") # 設(shè)置標(biāo)題
 
 
if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())

四、animation的方式刷新matplotlib

如果你在UI中的刷新頻率非常高,比如股票或期貨的tick數(shù)據(jù),上面的刷新方式就有點不夠用了,雖然也能刷新但是又可能會閃屏的情況很不舒服,高頻刷新還是用animation方式刷新。
使用animation 需要增加導(dǎo)入matplotlib.animation模塊的FuncAnimation方法,全部導(dǎo)入模塊如下:

?
1
2
3
4
5
6
import matplotlib
matplotlib.use("Qt5Agg") # 聲明使用pyqt5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg # pyqt5的畫布
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.animation import FuncAnimation

FuncAnimation的基礎(chǔ)使用這里就不贅述了,論壇內(nèi)搜索就可以找到,只提一個可能存在坑的地方,數(shù)據(jù)更新函數(shù)是嵌套在繪圖方法plot_tick內(nèi)的(可不要以為這是格式錯誤)。這里直接上代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class MyMatPlotAnimation(FigureCanvasQTAgg):
  """
  創(chuàng)建一個畫板類,并把畫布放到容器(畫板上)FigureCanvasQTAgg,再創(chuàng)建一個畫圖區(qū)
  """
  def __init__(self, width=10, heigh=10, dpi=100):
    # 創(chuàng)建一個Figure,該Figure為matplotlib下的Figure,不是matplotlib.pyplot下面的Figure
    self.figs = Figure(figsize=(width, heigh), dpi=dpi)
    super(MyMatPlotAnimation, self).__init__(self.figs)
    self.figs.patch.set_facecolor('#01386a') # 設(shè)置繪圖區(qū)域顏色
    self.axes = self.figs.add_subplot(111)
 
  def set_mat_func(self, t, s):
    """
    初始化設(shè)置函數(shù)
    """
    self.t = t
    self.s = s
    self.axes.cla()
    self.axes.patch.set_facecolor("#01386a") # 設(shè)置ax區(qū)域背景顏色
    self.axes.patch.set_alpha(0.5) # 設(shè)置ax區(qū)域背景顏色透明度
 
    # self.axes.spines['top'].set_color('#01386a')
    self.axes.spines['top'].set_visible(False) # 頂邊界不可見
    self.axes.spines['right'].set_visible(False) # 右邊界不可見
 
    self.axes.xaxis.set_ticks_position('bottom') # 設(shè)置ticks(刻度)的位置為下方
    self.axes.yaxis.set_ticks_position('left') # 設(shè)置ticks(刻度) 的位置為左側(cè)
    # 設(shè)置左、下邊界在(0,0)處相交
    # self.axes.spines['bottom'].set_position(('data', 0)) # 設(shè)置x軸線再Y軸0位置
    self.axes.spines['left'].set_position(('data', 0)) # 設(shè)置y軸在x軸0位置
    self.plot_line, = self.axes.plot([], [], 'r-', linewidth=1) # 注意‘,'不可省略
    
  def plot_tick(self):
    plot_line = self.plot_line
    plot_axes = self.axes
    t = self.t
    
    def upgrade(i): # 注意這里是plot_tick方法內(nèi)的嵌套函數(shù)
      x_data = [] # 這里注意如果是使用全局變量self定義,可能會導(dǎo)致繪圖首位相聯(lián)
      y_data = []
      for i in range(len(t)):
        x_data.append(i)
        y_data.append(self.s[i])
      plot_axes.plot(x_data, y_data, 'r-', linewidth=1)
      return plot_line, # 這里也是注意‘,'不可省略,否則會報錯
      
    ani = FuncAnimation(self.figs, upgrade, blit=True, repeat=False)
    self.figs.canvas.draw() # 重繪還是必須要的
 
class MainDialogImgBW(QtWidgets.QMainWindow):
  def __init__(self):
    super(MainDialogImgBW_, self).__init__()
    self.setWindowTitle("顯示matplotlib")
    self.setObjectName("widget")
    self.resize(800, 600)
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(0, 0, 800, 600))
    self.canvas = MyMatPlotAnimation(width=5, heigh=4, dpi=100)
    self.plotcos()
    self.hboxlayout = QtWidgets.QHBoxLayout(self.label)
    self.hboxlayout.addWidget(self.canvas)
 
  def plotcos(self):
    t = np.arange(0.0, 5.0, 0.01)
    s = np.cos(2 * np.pi * t)
    self.canvas.set_mat_func(t, s)
    self.canvas.plot_tick()
 
 
if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv)
  main = MainDialogImgBW()
  main.show()
  sys.exit(app.exec_())

到此這篇關(guān)于詳解pyqt5的UI中嵌入matplotlib圖形并實時刷新(挖坑和填坑)的文章就介紹到這了,更多相關(guān)pyqt5嵌入matplotlib圖形內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/wuwei_201/article/details/106106387

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人免费网站 | 欧美国产精品一区二区三区 | 99精品欧美一区二区三区综合在线 | 精品久久久久久久久久久久 | 91视频免费网站 | 黄色一级片毛片 | 欧美一区二区免费在线 | 国产一区二区久久 | 午夜精品久久久久久久久久久久 | 亚洲区在线 | 午夜在线 | 国产成人免费在线 | 北条麻妃在线一区二区免费播放 | 中文字幕日韩欧美 | 久久精品国产99国产精2020新增功能 | 国产999精品久久久久久麻豆 | 欧美综合第一页 | 亚洲国产精品久久久久 | 国产资源视频在线观看 | 亚洲理论电影在线观看 | 日产精品一区二区三区在线观看 | 色网站在线观看 | 中文字幕综合在线 | 免费久久99精品国产婷婷六月 | 国产资源在线观看 | 99精品99| 欧美成人二区 | 亚洲高清色综合 | 日本在线免费观看 | 久久精品视频网站 | 网站av| 久久精品一区二区三区中文字幕 | 国产久 | 久草视频网 | 爱操在线 | 精品在线 | 欧美大片在线观看 | 亚洲视频在线观看免费 | 国产精品色一区二区三区 | 国产日韩成人 | 中文字幕人成乱码在线观看 |