pyqtgraph 动态图:添加行以打开 GUI
pyqtgraph dynamic plot: add line to open GUI
我正在尝试向现有的打开的 Plot 添加新行。
我写了一个看门狗看一个有测量数据的文件夹。每隔几秒就会有一个新的数据文件。我尝试生成的应用程序应该在被看门狗触发时读取文件并将数据添加到绘图中。
更新现有数据时,使用 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()也会阻塞,window关闭时会解锁,也就是说starter之后的所有代码只有关闭后才会执行window。另一方面,您不应在 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()
我正在尝试向现有的打开的 Plot 添加新行。
我写了一个看门狗看一个有测量数据的文件夹。每隔几秒就会有一个新的数据文件。我尝试生成的应用程序应该在被看门狗触发时读取文件并将数据添加到绘图中。
更新现有数据时,使用 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()也会阻塞,window关闭时会解锁,也就是说starter之后的所有代码只有关闭后才会执行window。另一方面,您不应在 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()