2016-07-19 12 views
1

PyQtプロットウィジェットを使用してリアルタイムデータプロットを作成しようとしています。私は、PyQtがリアルタイムグラフをプロットするための最良の選択肢だと読んだが、今まで私は何の成功も見せていない。PyQt PlotWidgetによるリアルタイムプロット - エラーメッセージPlotWidgetオブジェクトが呼び出せない

私は方法followed hereを使ってランダムなデータをプロットしようとしましたが、この方法はPyQtプロットウィジェットには当てはまりません。

x軸とy軸のランダムな点をプロットするGUIを生成するために、次のコードをコンパイルしました。しかし、私はエラーを取得する:

PlotWidget object is not callable

from PyQt4.QtGui import * 
from PyQt4.QtCore import * 

import numpy as np 
import pyqtgraph as pg 
import sys 


class Window(QMainWindow): 

    def __init__(self): 
     super(Window, self).__init__() 
     self.setWindowIcon(QIcon('pythonlogo.png')) 
     self.setGeometry(50,50,700,300) 
     self.home() 

    def home(self): 

     #Timer for Plot calls the update function 

     self.plot = pg.PlotWidget(self) 
     self.timer2 = pg.QtCore.QTimer() 
     self.timer2.timeout.connect(self.update) 
     self.timer2.start(16) 

     #Plot widget postion 
     self.plot.move(200,50) 
     self.plot.resize(450,200) 

     self.show() 

    def update(self): 
     x = np.random.normal(size=1000) 
     y = np.random.normal(size=1000) 
     self.plot(x,y,clear=True) 

def run():  
     app=QApplication(sys.argv) 
     GUI = Window() 
     sys.exit(app.exec_()) 

run() 

答えて

1

私は同様の問題に直面してきました。しかし結局私はリアルタイムのプロットを作った!

私は自分のコードを見て、あなたと関係のないすべてのものを投げ捨てました。ライブグラフを表示するために必要な基本コードはここにあります:

################################################################### 
#                 # 
#      PLOTTING A LIVE GRAPH      # 
#     ----------------------------     # 
#   EMBED A MATPLOTLIB ANIMATION INSIDE YOUR    # 
#   OWN GUI!            # 
#                 # 
################################################################### 


import sys 
import os 
from PyQt4 import QtGui 
from PyQt4 import QtCore 
import functools 
import numpy as np 
import random as rd 
import matplotlib 
matplotlib.use("Qt4Agg") 
from matplotlib.figure import Figure 
from matplotlib.animation import TimedAnimation 
from matplotlib.lines import Line2D 
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas 
import time 
import threading 



def setCustomSize(x, width, height): 
    sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) 
    sizePolicy.setHorizontalStretch(0) 
    sizePolicy.setVerticalStretch(0) 
    sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth()) 
    x.setSizePolicy(sizePolicy) 
    x.setMinimumSize(QtCore.QSize(width, height)) 
    x.setMaximumSize(QtCore.QSize(width, height)) 

'''''' 

class CustomMainWindow(QtGui.QMainWindow): 

    def __init__(self): 

     super(CustomMainWindow, self).__init__() 

     # Define the geometry of the main window 
     self.setGeometry(300, 300, 800, 400) 
     self.setWindowTitle("my first window") 

     # Create FRAME_A 
     self.FRAME_A = QtGui.QFrame(self) 
     self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name()) 
     self.LAYOUT_A = QtGui.QGridLayout() 
     self.FRAME_A.setLayout(self.LAYOUT_A) 
     self.setCentralWidget(self.FRAME_A) 

     # Place the zoom button 
     self.zoomBtn = QtGui.QPushButton(text = 'zoom') 
     setCustomSize(self.zoomBtn, 100, 50) 
     self.zoomBtn.clicked.connect(self.zoomBtnAction) 
     self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0)) 

     # Place the matplotlib figure 
     self.myFig = CustomFigCanvas() 
     self.LAYOUT_A.addWidget(self.myFig, *(0,1)) 

     # Add the callbackfunc to .. 
     myDataLoop = threading.Thread(name = 'myDataLoop', target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,)) 
     myDataLoop.start() 

     self.show() 

    '''''' 


    def zoomBtnAction(self): 
     print("zoom in") 
     self.myFig.zoomIn(5) 

    '''''' 

    def addData_callbackFunc(self, value): 
     # print("Add data: " + str(value)) 
     self.myFig.addData(value) 



''' End Class ''' 


class CustomFigCanvas(FigureCanvas, TimedAnimation): 

    def __init__(self): 

     self.addedData = [] 
     print(matplotlib.__version__) 

     # The data 
     self.xlim = 200 
     self.n = np.linspace(0, self.xlim - 1, self.xlim) 
     a = [] 
     b = [] 
     a.append(2.0) 
     a.append(4.0) 
     a.append(2.0) 
     b.append(4.0) 
     b.append(3.0) 
     b.append(4.0) 
     self.y = (self.n * 0.0) + 50 

     # The window 
     self.fig = Figure(figsize=(5,5), dpi=100) 
     self.ax1 = self.fig.add_subplot(111) 


     # self.ax1 settings 
     self.ax1.set_xlabel('time') 
     self.ax1.set_ylabel('raw data') 
     self.line1 = Line2D([], [], color='blue') 
     self.line1_tail = Line2D([], [], color='red', linewidth=2) 
     self.line1_head = Line2D([], [], color='red', marker='o', markeredgecolor='r') 
     self.ax1.add_line(self.line1) 
     self.ax1.add_line(self.line1_tail) 
     self.ax1.add_line(self.line1_head) 
     self.ax1.set_xlim(0, self.xlim - 1) 
     self.ax1.set_ylim(0, 100) 


     FigureCanvas.__init__(self, self.fig) 
     TimedAnimation.__init__(self, self.fig, interval = 50, blit = True) 

    def new_frame_seq(self): 
     return iter(range(self.n.size)) 

    def _init_draw(self): 
     lines = [self.line1, self.line1_tail, self.line1_head] 
     for l in lines: 
      l.set_data([], []) 

    def addData(self, value): 
     self.addedData.append(value) 

    def zoomIn(self, value): 
     bottom = self.ax1.get_ylim()[0] 
     top = self.ax1.get_ylim()[1] 
     bottom += value 
     top -= value 
     self.ax1.set_ylim(bottom,top) 
     self.draw() 


    def _step(self, *args): 
     # Extends the _step() method for the TimedAnimation class. 
     try: 
      TimedAnimation._step(self, *args) 
     except Exception as e: 
      self.abc += 1 
      print(str(self.abc)) 
      TimedAnimation._stop(self) 
      pass 

    def _draw_frame(self, framedata): 
     margin = 2 
     while(len(self.addedData) > 0): 
      self.y = np.roll(self.y, -1) 
      self.y[-1] = self.addedData[0] 
      del(self.addedData[0]) 


     self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ]) 
     self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin])) 
     self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin]) 
     self._drawn_artists = [self.line1, self.line1_tail, self.line1_head] 



''' End Class ''' 


# You need to setup a signal slot mechanism, to 
# send data to your GUI in a thread-safe way. 
# Believe me, if you don't do this right, things 
# go very very wrong.. 
class Communicate(QtCore.QObject): 
    data_signal = QtCore.pyqtSignal(float) 

''' End Class ''' 



def dataSendLoop(addData_callbackFunc): 
    # Setup the signal-slot mechanism. 
    mySrc = Communicate() 
    mySrc.data_signal.connect(addData_callbackFunc) 

    # Simulate some data 
    n = np.linspace(0, 499, 500) 
    y = 50 + 25*(np.sin(n/8.3)) + 10*(np.sin(n/7.5)) - 5*(np.sin(n/1.5)) 
    i = 0 

    while(True): 
     if(i > 499): 
      i = 0 
     time.sleep(0.1) 
     mySrc.data_signal.emit(y[i]) # <- Here you emit a signal! 
     i += 1 
    ### 
### 




if __name__== '__main__': 
    app = QtGui.QApplication(sys.argv) 
    QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique')) 
    myGUI = CustomMainWindow() 


    sys.exit(app.exec_()) 

'''''' 

ただ試してみてください。このコードをコピーして新しいpython-fileに貼り付け、それを実行します。私は、私はなっていたエラーを解決することができたし、リアルタイムでプロットウィジェットを更新することができました

enter image description here

+0

ありがとうございました。あなたは本当にきれいなアプリを作っています:) PyQt4プロットウィジェットに対してMatplotlibキャンバスを使用することに決めました。あなたがPyQt4で成功しなかったのでこれはありますか?私はPyQt4の主な描画の1つがリアルタイムデータをプロットできるという印象を受けていましたが、これはウィジェットには当てはまりません。スレッドセーフな方法を使用しないと、非常に間違っているとあなたのコードで気付きましたか?リスクは何ですか?私はRpiに接続された温度センサーからデータ信号を受信します。この回答をもう一度ありがとう、それは非常に便利です:) – alkey

+0

こんにちはアランキー。 matplotlibライブラリには、あらゆる種類のアニメーションを作成するための素晴らしいサポートがあります。そしてそのコードはグラフが滑らかになるように最適化されています。私にとって、それは重要です:-)。まあ、スレッドの安全でない方法については、コードを「スレッドセーフ」にする前に、私は一度非常に奇妙なエラーメッセージを表示しました。あなたが興味を持っているなら、私はあなたのためにそれを見ることができます。とにかく、私が答えたコードは100%スレッドセーフです。 0.1秒ごとに新しいデータポイントがグラフに送信されます。それは信号スロット機構を介して「放出」される。私が生成する副機能である –

+0

の代わりに)温度データを送信すると、温度グラフが表示されます。私を信じて、マイクロコントローラから同時に12個の信号が来るようにしました。原子力発電所のコントロールパネルを見ているかのように、すべての12個の信号がスムーズに移動します;-) –

0

OK:あなたは美しいなめらかなライブグラフを取得する必要があります。以下のコードは、いくつかの基本的な例を示しています。 PyQtでリアルタイムプロットの機能を示すために、この回答を時間外に改善したいと思います。

from PyQt4.QtGui import * 
from PyQt4.QtCore import * 

import numpy as np 
import pyqtgraph as pg 
import random 
import sys 
import datetime 


class Window(QMainWindow): 

    def __init__(self): 
     super(Window, self).__init__() 
     self.setWindowIcon(QIcon('pythonlogo.png')) 
     self.setGeometry(50,50,700,900) 
     self.home() 

    def home(self):  

     #Labels 

     staticLbl = QLabel("Static Plot",self) 
     staticLbl.move(10,50) 

     dynamicLbl = QLabel("Random Plot",self) 
     dynamicLbl.move(10,300) 

     conLbl = QLabel("Continuous Plot",self) 
     conLbl.move(10,550) 

     #Static plot widget: 

     staticPlt = pg.PlotWidget(self) 
     x = np.random.normal(size=10) 
     y = np.random.normal(size=10) 

     staticPlt.plot(x,y,clear=True) 

     staticPlt.move(200,50) 
     staticPlt.resize(450,200) 

     #Code to run to random plot using timer: 

     self.dynamicPlt = pg.PlotWidget(self) 

     self.dynamicPlt.move(200,300) 
     self.dynamicPlt.resize(450,200) 

     self.timer2 = pg.QtCore.QTimer() 
     self.timer2.timeout.connect(self.update) 
     self.timer2.start(200) 

     #Code to run to get continous plot using timer: 

     self.continuousPlt = pg.PlotWidget(self) 

     self.continuousPlt.move(200,550) 
     self.continuousPlt.resize(450,200) 

     self.timer3 = pg.QtCore.QTimer() 
     self.timer3.timeout.connect(self.cUpdate) 
     self.timer3.start(200) 

     self.show() 

    def update(self): 
     z = np.random.normal(size=1) 
     u = np.random.normal(size=1) 
     self.dynamicPlt.plot(z,u,pen=None, symbol='o') 

    def cUpdate(self): 
     now = datetime.datetime.now() 
     s = np.array([now.second]) 

     self.continuousPlt.plot(s,s,pen=None, symbol='o') 


def run():  
     app=QApplication(sys.argv) 
     GUI = Window() 
     sys.exit(app.exec_()) 

run() 
関連する問題