首页 > 解决方案 > 使用 pyqtgraph 和 python 线程作为类的实时绘图

问题描述

所以我目前正在尝试做的是创建一个可以用于任何类型的实时绘图的类。原则上我只想调用类变量并使用 set_data(x,y) 之类的命令。我遇到的问题是我需要使用python线程来更新显示的图形。但是,当我在下面的代码中使用线程时,在我想要更新绘制的图形数据的代码末尾执行 while True 部分时,pyqtgraph 窗口不再响应。是否有替代方法来更新图表而不是我不工作的线程方法?我阅读了有关 QtCore 计时器的信息,但这种方法也像我在这里使用的普通线程一样崩溃。

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import random
import threading
import time

from pyqtgraph.dockarea import *


class liveplot(threading.Thread):
    def __init__(self, updating_time__s=0.01):
        """
        Contructor of the liveplot class

        """
        self.app = pg.mkQApp("DockArea Example")
        self.win = QtGui.QMainWindow()
        self.area = DockArea()
        self.win.setCentralWidget(self.area)
        self.win.resize(1000, 500)
        self.win.setWindowTitle('pyqtgraph example: dockarea')

        threading.Thread.__init__(self)     # Init thread class
        self._lock = threading.Lock()       # Needed to prevent data races in threads.

        self._stop_thread = False

        self.widgetlist = []
        self.docklist = []
        self.x_data = []
        self.y_data = []
        self.plotlist = []
        self.updateing_time__s = updating_time__s
        
        self._last_measurement_time__s = time.time()
    
        self.start()        
                         

    def plot(self, widgetnumber, axis, x_data, y_data):
        self.plotlist.append(self.widgetlist[widgetnumber].plot(x_data, y_data))
        self.x_data = x_data
        self.y_data = y_data
        

    def add_widget(self, docktitle="Test", docksize=(500,200), widgettitle="Test"):
        d = Dock(docktitle, size=docksize)
        w = pg.PlotWidget(title=widgettitle)
        d.addWidget(w)
        self.docklist.append(d)
        self.widgetlist.append(w)
        self.area.addDock(d)


    def set_data(self, x_data, y_data):
        self.x_data = x_data
        self.y_data = y_data
        self.new_data_available = True

    def update_plot_data(self):
         # In the end I want it to be as general as possible but in the moment I just want it to work properly
         # for the first part so I only have one element in the plotlist.
        self.plotlist[0].setData(self.x_data.tolist(), self.y_data.tolist()) 


    def show(self):
        self.win.show()


    def run(self):
        """
        Main

        """
        # Run thread until stop() is called
        while True:
            if self._stop_thread:
                break

            current_time__s = time.time()
            time_since_last_measurement__s = current_time__s - self._last_measurement_time__s

            if time_since_last_measurement__s >= self.updateing_time__s:
                self._last_measurement_time__s = current_time__s

                if len(self.plotlist) > 0:
                    self.update_plot_data()


    def stop(self):
        with self._lock:
            self._stop_thread = True


x = liveplot()
x.add_widget()
x_dat = np.linspace(0, 10, 100)
y_dat = np.sin(x_dat)
x.add_widget()
x.plot(widgetnumber=0, axis=0, x_data=x_dat, y_data=y_dat)
x.show()

while True:
    time.sleep(1)
    x_dat = np.roll(x_dat, 1)  
    x_dat[-1] = x_dat[-2] + 1  # Add a new value 1 higher than the last.

    y_dat = np.roll(y_dat, 1)  
    y_dat[-1] = random.randint(0,100)  # Add a new random value.
    x.set_data(x_dat, y_dat)

标签: pythonmultithreadingpyqtpyqt5pyqtgraph

解决方案


推荐阅读