[英]How to process data and display it simultaneously in PyQt5 and matplotlib
我正在嘗試擴展此處介紹的示例,說明如何將matplotlib
圖集成到 PyQt5 window 中並在應用程序運行時對其進行更新。
我對上面鏈接的代碼所做的更改是 plot 更新時的條件,即代替計時器,我向應用程序添加了一個按鈕,該按鈕鏈接到名為simulate
的 function 並運行for
-循環。 在循環內部,我們調用update_plot
function,其他一切都保持不變。
def simulate(self, ydata):
for k in trange(0, 500, 10):
tmp = np.random.uniform(0, 1, size=(2, 1000))
self.xdata = tmp[0]
self.ydata = tmp[1]
self.update_plot()
完整的代碼是
import sys
from PyQt5.QtWidgets import QVBoxLayout, QSizePolicy, QWidget, QPushButton, QHBoxLayout, QSpacerItem
from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import random
import numpy as np
from time import sleep
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.figure import Figure
class MplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
widget = QWidget(self)
self.setCentralWidget(widget)
vlay = QVBoxLayout(widget)
hlay = QHBoxLayout()
vlay.addLayout(hlay)
pybutton = QPushButton('Fit!', self)
pybutton.clicked.connect(self.simulate)
hlay2 = QHBoxLayout()
hlay2.addWidget(pybutton)
hlay2.addItem(QSpacerItem(1000, 10, QSizePolicy.Expanding))
vlay.addLayout(hlay2)
self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
vlay.addWidget(self.canvas)
self.n_data = 999
self.xdata = list(range(self.n_data))
self.ydata = [random.uniform(0, 1) for i in range(self.n_data)]
# We need to store a reference to the plotted line
# somewhere, so we can apply the new data to it.
self._plot_ref = None
self.update_plot()
self.show()
def simulate(self):
for k in range(0, 5):
print(k)
tmp = np.random.uniform(0, 1, size=(2,self.n_data))
self.xdata = tmp[0]
self.ydata = tmp[1]
self.update_plot()
sleep(0.5)
def update_plot(self):
# Drop off the first y element, append a new one.
#self.ydata = self.ydata[1:] + [random.randint(0, 10)]
# Note: we no longer need to clear the axis.
if self._plot_ref is None:
plot_refs = self.canvas.axes.plot(self.xdata, self.ydata, 'r')
self._plot_ref = plot_refs[0]
else:
self._plot_ref.set_ydata(self.ydata)
# Trigger the canvas to update and redraw.
self.canvas.draw()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
現在發生的情況是,每當您單擊按鈕時self.simulate()
被調用,因此for
循環開始......正如您在 function 中看到的那樣,我每次都調用self.update_plot
,但顯示的 plot 只會得到循環結束后更新,即 function 完成...
有人可以解釋發生了什么嗎?
我認為 Qt 僅在主事件循環空閑時刷新顯示。 因此,當您運行simulate
方法時,它無法刷新。 對此的快速解決方法是在update_plot()
之后添加app.processEvents()
) 。
如果您有幾個需要經常更新的 GUI 項目,那么 processEvents 技巧將不會很好地工作,您將不得不開始查看線程。 特別是 QThreads,因為它們的設計目的是與 Qt 配合得很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.