【问题标题】:how to force matplotlib to update a plot如何强制 matplotlib 更新绘图
【发布时间】:2011-03-31 15:43:05
【问题描述】:

我正在尝试构建一个小图形用户界面,它有一个每次读取新数据样本时都会更新的图形。我不希望使用计时器运行它,因为数据将以不同的时间间隔到达。相反,我正在尝试使用信号进行实现,其中数据收集函数将在读取数据时发出信号,然后绘画函数将在绘画完成时发出信号。

现在出现的问题是,一旦我调用 canvas.draw(),画布就没有更新。当这个程序运行时, data_collect() 和 paint() 交替发送信号,但是直到我停止进程之后,这个数字才会更新。如何在调用 paint() 时强制 matplotlib 更新图形?

下面是一段相对简单的示例代码,它不是最佳的,但希望能传达我正在尝试做的事情的味道......

N_length = 150;
count = [0];

def sinval(delay):

    k = 0;
    x = [];

    # set up data vector with sinusoidal data in it.
    while k < N_length:  
        x.append(math.sin(2*math.pi*k/N_length));
        k += 1;

    def next():

        time.sleep(delay);
        outstring = "%0.3e" % (x[count[0]]);

        if (count[0] == (N_length-1)):
            count[0] = 0;
        else:
            count[0] += 1;

        return outstring;

    return next;


class DesignerMainWindow(QtGui.QMainWindow, Ui_mplMainWindow):

    def __init__(self, parent = None):
        super(DesignerMainWindow, self).__init__(parent)
        self.setupUi(self)

        QtCore.QObject.connect(self.mplStartButton, QtCore.SIGNAL("clicked()"), self.start_graph);
        QtCore.QObject.connect(self.mplStopButton, QtCore.SIGNAL("clicked()"), self.stop_graph);
        QtCore.QObject.connect(self.mplQuitButton, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()"));
        QtCore.QObject.connect(self, QtCore.SIGNAL("data_collect()"), self.data_collect);
        QtCore.QObject.connect(self, QtCore.SIGNAL("paint()"), self.paint);

    def start_graph(self):

        # generates first "empty" plots
        self.user = [];
        self.l_user, = self.mpl.canvas.ax.plot([], self.user, label='sine wave');

        # set up the axes. 
        self.mpl.canvas.ax.set_xlim(0, 300);
        self.mpl.canvas.ax.set_ylim(-1.1, 1.1);
        self.mpl.canvas.draw();

        # start the data collection process.
        self.delay = 0.05;
        self.next = sinval(self.delay);
        self.emit(QtCore.SIGNAL('data_collect()'));


    def data_collect(self):
        outstring = self.next();
        self.user.append(float(outstring.split()[0]));
        self.l_user.set_data(range(len(self.user)), self.user);
        self.emit(QtCore.SIGNAL('paint()'));


    def paint(self):
        self.mpl.canvas.draw();
        self.emit(QtCore.SIGNAL('data_collect()'));

【问题讨论】:

  • 是我遗漏了什么,还是您遗漏了所有绘图命令? data_collectpaint 似乎都没有任何会改变情节的情节命令(如self.mpl.canvas.ax.plot)。所以不会调用self.mpl.canvas.draw() 只是重新绘制相同的旧情节吗?
  • @~unutbu - 他正在使用self.l_user.set_data(...) 设置更新数据,而不是重新绘制所有内容。 (如果您只想更改绘图数据而不重绘轴刻度等,它比调用绘图更有效)
  • 我的理解是更新 l_user.set_data 然后调用 canvas.draw() 会自动刷新图形。我尝试将paint(self) 中的第一个命令更改为self.mpl.canvas.ax.plot(),但这似乎并没有完成这项工作。我应该如何更改此命令?谢谢 -
  • @Joe 和@user424211:好的,谢谢您的解释。

标签: python qt4 matplotlib pyqt4 signals-slots


【解决方案1】:

我猜想在 paint() 之后调用 QCoreApplication::processEvents 会有所帮助。更优雅的是有一个单独的 QThread 用于阅读。看看这个thread

【讨论】:

  • 谢谢!我不得不在 PyQt4 中调用 QtGui.QApplication.processEvents(),但这成功了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 2022-08-13
  • 2011-07-06
  • 1970-01-01
相关资源
最近更新 更多