【问题标题】:pyqtgraph dynamic plot: add line to open GUIpyqtgraph 动态绘图:添加行以打开 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()

【问题讨论】:

  • 显示看门狗代码

标签: python-3.x user-interface plot pyqtgraph


【解决方案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()

【讨论】:

  • 感谢您的快速答复。我想我到目前为止都明白了。但对我来说还有很多东西要学。
猜你喜欢
  • 2019-05-31
  • 2014-08-19
  • 2018-09-12
  • 2014-07-07
  • 2017-12-04
  • 1970-01-01
  • 2013-05-17
  • 2019-03-03
  • 2021-12-27
相关资源
最近更新 更多