2010-08-18 1 views
2

Я пытаюсь построить небольшой графический интерфейс, который имеет сюжет, который обновляется каждый раз, когда считывается новый образец данных. Я бы предпочел не запускать его таймером, так как данные будут поступать с разными интервалами. Вместо этого я пытаюсь выполнить реализацию с использованием сигналов, где функция сбора данных будет излучать сигнал при чтении данных, а затем функция рисования будет излучать сигнал, когда картина будет завершена.как заставить matplotlib обновить сюжет

Проблема, поскольку это прямо сейчас, заключается в том, что холст не обновляется, как только я вызываю canvas.draw(). Когда эта программа запускается, data_collect() и paint() чередуют сигналы отправки, но эта цифра не обновляется до тех пор, пока я не остановлю процесс. Как заставить matplotlib обновлять фигуру при вызове paint()?

То, что следует относительно простой кусок кода примера, который не является оптимальным, но, надеюсь, будет передать аромат, что я пытаюсь сделать ...

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()')); 
+0

Я что-то упустил или упустил все команды сюжета? Ни 'data_collect', ни' paint', похоже, не имеют каких-либо сюжетных команд (например, 'self.mpl.canvas.ax.plot'), которые могли бы изменить сюжет. Так что бы не называть 'self.mpl.canvas.draw()' просто перерисовывать один и тот же старый сюжет? – unutbu

+0

@ ~ unutbu - Он устанавливает обновление данных сюжета с помощью 'self.l_user.set_data (...)' вместо того, чтобы полностью переупорядочивать. (Это намного эффективнее вызова графика, если вы просто хотите изменить данные графика, а не перерисовывать тики оси и т. Д.) –

+0

я понял, что обновление l_user.set_data, а затем вызов canvas.draw() будет автоматически обновляться рисунок. Я попытался изменить первую команду в paint (self) на self.mpl.canvas.ax.plot(), но это, похоже, не выполняло эту работу. как мне изменить эту команду? спасибо - – user424211

ответ

1

Я предположил бы, что вызов QCoreApplication :: processEvents after paint() поможет. Более элегантным было бы иметь отдельный QThread для чтения. Взгляните на это thread.

+0

Спасибо! Мне пришлось вызывать QtGui.QApplication.processEvents() в PyQt4, но это сделало трюк. – user424211