python-3.x - pyqtgraph 动态绘图:添加行以打开 GUI
问题描述
我正在尝试将新行添加到现有且打开的绘图中。
我写了一个看门狗来监视一个包含测量数据的文件夹。每隔几秒就会有一个新的数据文件。我尝试生成的应用程序应该在看门狗触发时读取文件并将数据添加到绘图中。
更新现有数据时,使用 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()
解决方案
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()
推荐阅读
- amazon-eks - 使用 eksctl 创建 aws EKS Kubernetes 集群时出错
- java - Java 销毁对象(清除所有引用)
- c++ - 导出具有外部依赖项的 cmake 项目的既定方法是什么?
- php - 使用不同的值更新多个 Eloquent 模型
- git - 如何在 Ansible Tower Playbook 中引用 git 文件
- c# - 如何防止自定义 TryParse 方法出现可能的空引用警告?
- flutter - Flutter LayoutBuilder 类的高宽类型有哪些?
- c# - 创建使用返回任务的方法的类的任何缺点
但是是同步方法而不是返回 T 的方法 - python - 在 RandomForest 中,特征选择精度永远不会提高到 %0.1 以上
- android - 单击列表视图项目时显示图像