python - 我怎样才能修改这个代码,这样我就不会每次都重新绘制我的图,matplotlib

标签 python qt matplotlib pyqt

我正在从设备中获取数据并想要绘制其电压,并将该图嵌入到用户界面中。我在这里使用了这个例子:http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html

这个示例工作正常,但是当我添加 2 个或更多图表时,整个 UI 变得非常慢(使用 RPi3)并且 CPU 使用率非常高。我意识到这可能是因为图表不断被清除和重新绘制。

我的代码如下所示:

class MyMplCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=2, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)

        self.compute_initial_figure()

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

    def compute_initial_figure(self):
        pass

class MyDynamicMplCanvas(MyMplCanvas):

    def __init__(self, *args, **kwargs):
        MyMplCanvas.__init__(self, *args, **kwargs)

    def compute_initial_figure(self):
        self.axes.cla()

    def update_figure(self,voltage):
        self.axes.cla()
        self.axes.plot(np.linspace(0,len(voltage)-1,num = len(voltage)), voltage, 'b')  
        self.axes.set_xlabel("Time")
        self.draw()


class worker_thread(QThread):
... #worker thread stuff here

class Monitor(QtGui.QMainWindow):

    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.exit_button.clicked.connect(exit)
        self.ui.go_button.clicked.connect(self.start_monitoring)
        self.ui.print_button.clicked.connect(self.test_print)

        self.ac_graph = QtGui.QWidget(self)
        self.ac_1_graph = MyDynamicMplCanvas(self.ac_graph,width = 10, height =3 , dpi = 60)
        self.ui.mplvl.addWidget(self.ac_1_graph)
        self.ac_1_graph.axes.set_xlabel("Time")

        self.dc_graph = QtGui.QWidget(self)
        self.dc_2_graph = MyDynamicMplCanvas(self.dc_graph,width = 10, height =3 , dpi = 60)
        self.ui.mplvl_2.addWidget(self.dc_2_graph)      

        self.ac1_voltage_values = []
        self.ac1_current_values = []
        self.dc2_voltage_values = []

    def start_monitoring(self): 

        self.worker_thread = worker_thread()

        self.connect(self.worker_thread,SIGNAL('grid_done'),      self.update_ac_dc_info)

    def update_plot_values(self, y_value, y_list):
        y_list.append(y_value)
        if (len(y_list) == 61):
            del y_list[0]
        return y_list

    def update_ac_dc_info(self,grid_info):
        self.ac1_voltage_values = self.update_plot_values((grid_info['ac1_voltage']/10),self.ac1_voltage_values)
        self.ac_1_graph.update_figure(self.ac1_voltage_values)

本质上,当数据从我的设备返回时,我从worker_thread发出一个信号,触发我的UI在主线程以及绘图中更新。此时,我如何让 matplotlib 接受新出现的点而不重新绘制整个内容?我读过的许多示例都使用了 pyplot,但我无法使用它,因为我需要将其嵌入到现有的 UI 中。

最佳答案

您不必每次有新数据时都清除轴,只需重新绘制点线即可。这会节省一些时间。

class MyDynamicMplCanvas(MyMplCanvas):

    def __init__(self, *args, **kwargs):
        MyMplCanvas.__init__(self, *args, **kwargs)

    def compute_initial_figure(self):
        # empty plot
        self.line,  = self.axes.plot([],[], color="b")
        self.axes.set_xlabel("Time") # xlabel will not change over time

    def update_figure(self,voltage):

        self.line.set_data(np.linspace(0,len(voltage)-1,num = len(voltage)), voltage)  
        # now you need to take care of the axis limits yourself
        self.axes.set_xlim([0,len(voltage])
        self.draw()

仅更新最后一个新点有点棘手,因为绘图由单个 Line2D 对象组成。您可以选择点图,每次新数据到达时您都可以在其中绘制一个新点。

关于python - 我怎样才能修改这个代码,这样我就不会每次都重新绘制我的图,matplotlib,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41734096/

相关文章:

python - 从时间序列数据中聚合重叠的 "all-previous-events"特征 - 在 Python 中

用于创建 SSH 连接的 Python 脚本

c++ - 从 QTreeWidget 覆盖复制文本操作

c++ - Frameles 和透明窗口不起作用! Qt 部件

Python Matplotlib - 保存的图像在使用 for 循环时被覆盖

python - pandas批量API请求

python - 将 WAV 字节从 POST 数据保存到磁盘 (cherrypy)

django - 仅接收作为参数传递给 http get 命令的字符串的一部分 - 可能是分号?

python - 将 Sklearn 数字大小从 8*8 扩展到 32*32

python - regplot() 的稳健选项到底有什么作用?