pyqtgraph 动态绘图:添加行以打开 GUI
Posted
技术标签:
【中文标题】pyqtgraph 动态绘图:添加行以打开 GUI【英文标题】:pyqtgraph dynamic plot: add line to open GUI 【发布时间】:2020-06-09 00:11:21 【问题描述】:我正在尝试将新行添加到现有和打开的绘图中。
我写了一个看门狗来监视一个包含测量数据的文件夹。每隔几秒就会有一个新的数据文件。我尝试生成的应用程序应该在被看门狗触发时读取文件并将数据添加到绘图中。
在更新现有数据时,使用 QTimer 和其他东西很容易进行动态绘图,但我没有新行的钩子。
另外,当我想在 _exec() 上进行绘图的同时运行脚本时,是否必须使用多线程?
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pq
import sys
import numpy as np
import time
class Plot2d(object):
def __init__(self):
self.traces = dict()
self.num = 0
pq.setConfigOptions(antialias=True)
self.app = QtGui.QApplication(sys.argv)
self.win = pq.GraphicsWindow(title='examples')
self.win.resize(1000, 600)
self.win.setWindowTitle('Windowtitle')
self.canvas = self.win.addPlot(title='Plot')
def starter(self):
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
def trace(self, name, dataset_x, dataset_y):
if name in self.traces:
self.traces[name].setData(dataset_x, dataset_y)
else:
self.traces[name] = self.canvas.plot(pen='y')
def update(self, i):
x_data = np.arange(0, 3.0, 0.01)
y_data = x_data*i
self.trace(str(i), x_data, y_data)
self.trace(str(i), x_data, y_data)
if __name__ == '__main__':
p = Plot2d()
p.update(1)
p.starter()
time.sleep(1)
p.update(2)
这是我尝试过的。当目录中有新数据可用时,应该由看门狗调用更新函数。
import time as time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
if __name__ == "__main__":
patterns = "*"
ignore_patterns = ""
ignore_directories = False
case_sensitive = True
go_recursively = False
my_event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)
def on_created(event):
print(f" event.src_path has been created!") #this function should call the plot update
my_event_handler.on_created = on_created
path = (r'C:\Users\...') #path from GUI at some point
my_observer = Observer()
my_observer.schedule(my_event_handler, path, recursive=go_recursively)
my_observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
my_observer.stop()
my_observer.join()
【问题讨论】:
显示看门狗代码 【参考方案1】:exec_() 方法是阻塞的,所以 starter() 也是阻塞的,并且会在关闭窗口时解锁,这意味着 starter 之后的所有代码只有在关闭窗口后才会执行。另一方面,您不应该在 GUI 线程中使用 time.sleep,因为它会阻止 GUI 事件循环的执行。
根据所使用的技术,提供了更新元素的方法,在 Qt 的情况下,适当的方法是使用信号,以便将看门狗的所有逻辑封装在一个 QObject 中,该 QObject 会将信息传输到 GUI通过一个信号,然后 GUI 将该信息用于绘图。
import sys
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pq
import numpy as np
class QObserver(QtCore.QObject):
dataChanged = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super(QObserver, self).__init__(parent)
patterns = "*"
ignore_patterns = ""
ignore_directories = False
case_sensitive = True
go_recursively = False
path = r"C:\Users\..." # path from GUI at some point
event_handler = PatternMatchingEventHandler(
patterns, ignore_patterns, ignore_directories, case_sensitive
)
event_handler.on_created = self.on_created
self.observer = Observer()
self.observer.schedule(event_handler, path, recursive=go_recursively)
self.observer.start()
def on_created(self, event):
print(
f" event.src_path has been created!"
) # this function should call the plot update
self.dataChanged.emit(np.random.randint(1, 5))
class Plot2d(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.traces = dict()
self.num = 0
pq.setConfigOptions(antialias=True)
self.app = QtGui.QApplication(sys.argv)
self.win = pq.GraphicsWindow(title="examples")
self.win.resize(1000, 600)
self.win.setWindowTitle("Windowtitle")
self.canvas = self.win.addPlot(title="Plot")
def starter(self):
if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"):
QtGui.QApplication.instance().exec_()
def trace(self, name, dataset_x, dataset_y):
if name in self.traces:
self.traces[name].setData(dataset_x, dataset_y)
else:
self.traces[name] = self.canvas.plot(pen="y")
@QtCore.pyqtSlot(object)
def update(self, i):
x_data = np.arange(0, 3.0, 0.01)
y_data = x_data * i
self.trace(str(i), x_data, y_data)
self.trace(str(i), x_data, y_data)
if __name__ == "__main__":
p = Plot2d()
qobserver = QObserver()
qobserver.dataChanged.connect(p.update)
p.starter()
【讨论】:
感谢您的快速答复。我想我到目前为止都明白了。但对我来说还有很多东西要学。以上是关于pyqtgraph 动态绘图:添加行以打开 GUI的主要内容,如果未能解决你的问题,请参考以下文章