簡體   English   中英

使用PyQt PlotWidget進行實時繪圖-錯誤消息PlotWidget對象不可調用

[英]Realtime plotting with PyQt PlotWidget - error message PlotWidget object is not callable

我正在嘗試使用PyQt圖小部件創建實時數據圖。 我讀到PyQt是繪制實時圖形的最佳選擇,但到目前為止我還沒有成功。

我嘗試使用此處遵循的方法繪制隨機數據但是似乎該方法不適用於PyQt繪圖小部件。

我已經編譯了以下代碼以生成GUI,該GUI在x和y軸上繪制隨機點; 但是我得到了錯誤:

PlotWidget對象不可調用

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()

我也遇到過類似的問題。 但是最后我得到了實時繪圖!

我看了一下我的代碼,並拋棄了所有與您無關的東西。 因此,您將在這里找到顯示實時圖形所需的基本代碼:

###################################################################
#                                                                 #
#                     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文件中,然后運行它。 您應該得到一個美麗的平滑實時圖形:

在此處輸入圖片說明

好的,這樣我就可以解決所收到的錯誤,並能夠實時更新繪圖小部件。 下面的代碼提供了一些基本示例。 我希望隨着時間的推移改善此答案,以顯示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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM