2010-08-18 7 views
2

새로운 데이터 샘플을 읽을 때마다 업데이트되는 플롯이있는 작은 GUI를 만들려고합니다. 데이터가 다른 간격으로 도착하기 때문에 타이머로 실행하지 않는 것이 좋습니다. 대신 데이터를 읽을 때 데이터 수집 함수가 신호를 내보내고 그림이 완료되면 페인팅 함수가 신호를 내 보냅니다. 신호를 사용하여 구현하려고합니다.matplotlib에서 플롯을 강제로 업데이트하는 방법

현재 나타나는 것처럼 문제는 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()')); 
+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()를 호출하면 자동으로 새로 고침됩니다. 그 그림. 페인트 (self)에서 첫 번째 명령을 self.mpl.canvas.ax.plot()으로 변경하려고 시도했지만 작업을 수행하지 않은 것 같습니다. 이 명령을 어떻게 변경해야합니까? 감사합니다. – user424211

답변

1

내가 QCoreApplication를 호출하는 것으로 추측에는 요 ... 최적이 아닌 예제 코드의 비교적 간단한 조각이다, 그러나 희망 내가 뭘하려는거야의 맛을 전달합니다 :: paint() 후 processEvents 도움이됩니다. 더 우아한 것은 독서를위한 별도의 QThread를 갖는 것입니다. 이 thread을보세요.

+0

감사! PyQt4에서 QtGui.QApplication.processEvents()를 호출해야했지만,이 트릭을했다. – user424211

관련 문제