pyqtgraph Dynami c сюжет: добавить строку, чтобы открыть GUI - PullRequest
1 голос
/ 25 февраля 2020

Я пытаюсь добавить новые строки в существующий и открытый график.

Я написал сторожевой таймер, просматривающий папку с данными измерений. Каждые несколько секунд будет новый файл данных. Приложение, которое я пытаюсь сгенерировать, должно прочитать файл при запуске сторожевым таймером и добавить данные на график.

Dynami c построение графиков с использованием QTimer, и все просто при обновлении существующих данных, но я не получить ловушку для новых строк.

Кроме того, мне нужно использовать многопоточность, когда я хочу запустить сценарий при построении графика на _exe c ()?

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 Ответ

0 голосов
/ 25 февраля 2020

Метод exec_ () блокирует, поэтому starter () тоже будет и будет разблокирован при закрытии окна, что означает, что весь код после starter будет выполняться только после закрытия окна. С другой стороны, вы не должны использовать time.sleep в потоке GUI, поскольку он блокирует выполнение события GUI l oop.

В зависимости от используемой технологии, способы обновления элементов в случае Qt подходящим способом является использование сигналов, так что все логики c сторожевого таймера будут инкапсулированы в объекте 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()
...