pyqt如何显示实时数据

来源:互联网 发布:php lastindexof 编辑:程序博客网 时间:2024/06/05 18:31
我有一个处理example.csv的后台程序,现在想把当前读行数实时显示到GUI界面中去。
就是这下面
PyQt的signal-slot机制不就是干这个的吗,你要输入的输入框比如LineEdit对应一个slot,处理的地方发送一个signal,剩下的就由PyQt自己做绑定,都不用具体的函数调用,代码看起来清爽多了

下面这个例子,BackendThread模拟后台线程,数据处理完了更新到前台,一秒钟一刷新,换成你自己的逻辑就可以

# -*- coding: utf-8 -*-from PyQt4.Qt import *from PyQt4.QtCore import *from PyQt4.QtGui import *import timeclass Backend(QThread):    update_date = pyqtSignal(QString)    def run(self):        while True:            data = QDateTime.currentDateTime()            self.update_date.emit(QString(str(data)))            time.sleep(1)class Window(QDialog):    def __init__(self):        QDialog.__init__(self)        self.resize(400, 100)        self.input = QLineEdit(self)        self.input.resize(400, 100)    def handleDisplay(self, data):        self.input.setText(data)if __name__ == '__main__':    import sys    app = QApplication(sys.argv)    b = Backend()    w = Window()    b.update_date.connect(w.handleDisplay)    b.start()    w.show()    app.exec_()
画动态更新图

通过定时器Timer触发事件,定时更新绘图,可以形成动态更新图片。下面的实例是学习《matplotlib for Pythondevelopers》一文的笔记。

实例如下:

通过self.user = self.user[1:] + [temp],每次删除列表的第一元素,在其尾部添加新的元素。这样完成user数据的动态更新。其他详细的解释见文中的注释部分。

[python] view plain copy
  1. #-*-coding:utf-8-*-  
  2. import wx  
  3. from matplotlib.figure import Figure  
  4. import matplotlib.font_manager as font_manager  
  5. import numpy as np  
  6. from matplotlib.backends.backend_wxagg import \  
  7.   FigureCanvasWxAgg as FigureCanvas  
  8. # wxWidgets object ID for the timer  
  9. TIMER_ID = wx.NewId()  
  10. # number of data points  
  11. POINTS = 300  
  12.   
  13. class PlotFigure(wx.Frame):  
  14.     """Matplotlib wxFrame with animation effect"""  
  15.     def __init__(self):  
  16.         wx.Frame.__init__(selfNone, wx.ID_ANY, title="CPU Usage Monitor", size=(600400))  
  17.         # Matplotlib Figure  
  18.         self.fig = Figure((64), 100)  
  19.         # bind the Figure to the backend specific canvas  
  20.         self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)  
  21.         # add a subplot  
  22.         self.ax = self.fig.add_subplot(111)  
  23.         # limit the X and Y axes dimensions  
  24.         self.ax.set_ylim([0100])  
  25.         self.ax.set_xlim([0, POINTS])  
  26.          
  27.         self.ax.set_autoscale_on(False)  
  28.         self.ax.set_xticks([])  
  29.         # we want a tick every 10 point on Y (101 is to have 10  
  30.         self.ax.set_yticks(range(010110))  
  31.         # disable autoscale, since we don't want the Axes to ad  
  32.         # draw a grid (it will be only for Y)  
  33.         self.ax.grid(True)  
  34.         # generates first "empty" plots  
  35.         self.user = [None] * POINTS  
  36.         self.l_user,=self.ax.plot(range(POINTS),self.user,label='User %')  
  37.   
  38.         # add the legend  
  39.         self.ax.legend(loc='upper center',  
  40.                            ncol=4,  
  41.                            prop=font_manager.FontProperties(size=10))  
  42.         # force a draw on the canvas()  
  43.         # trick to show the grid and the legend  
  44.         self.canvas.draw()  
  45.         # save the clean background - everything but the line  
  46.         # is drawn and saved in the pixel buffer background  
  47.         self.bg = self.canvas.copy_from_bbox(self.ax.bbox)  
  48.         # bind events coming from timer with id = TIMER_ID  
  49.         # to the onTimer callback function  
  50.         wx.EVT_TIMER(self, TIMER_ID, self.onTimer)  
  51.   
  52.     def onTimer(self, evt):  
  53.         """callback function for timer events"""  
  54.         # restore the clean background, saved at the beginning  
  55.         self.canvas.restore_region(self.bg)  
  56.                 # update the data  
  57.         temp =np.random.randint(10,80)  
  58.         self.user = self.user[1:] + [temp]  
  59.         # update the plot  
  60.         self.l_user.set_ydata(self.user)  
  61.         # just draw the "animated" objects  
  62.         self.ax.draw_artist(self.l_user)# It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)  
  63.         self.canvas.blit(self.ax.bbox)  
  64. if __name__ == '__main__':  
  65.     app = wx.PySimpleApp()  
  66.     frame = PlotFigure()  
  67.     t = wx.Timer(frame, TIMER_ID)  
  68.     t.Start(50)  
  69.     frame.Show()  
  70.     app.MainLoop()  

运行结果如下所示:

但程序运行在关闭的时候会出现应用程序错误,不知道什么问题。python不是有垃圾回收机制吗,难道是内存泄露?

猜测的原因可能是在关闭的时候正在绘图故导致应用程序出错。通过添加Frame的析构函数,停止更新则不会出现问题。

[python] view plain copy
  1. def __del__( self ):  
  2.     t.Stop()  
python 学习之读串口

Python中用于读串口的模块是 pySerial,使用非常的方便,可以从http://pypi.python.org/pypi/pyserial下载其安装包。

读取串口时首先导入包 import serial,其次设置读取哪一个口、波特率、数据位、停止位。

serial的原型如下:

[python] view plain copy
  1. class serial.Serial  
  2.   
  3.     __init__(port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, writeTimeout=None, dsrdtr=False, interCharTimeout=None)  
port:如COM1,COM2,COM3,COM4......如果port设置为0对应的为COM1

baudrate:设置波特率

bytesize:数据位

stopbits:停止位

timeout:超时时间

  • timeout = None: 长时间等待
  • timeout = 0: 不阻塞形式 (读完之后就返回)
  • timeout = x: x秒后超时 (float allowed)

简单的实例如下:

[python] view plain copy
  1. import serial   
  2. ser = serial.Serial()  
  3. ser.baudrate = 19200  
  4. ser.port = 0  
  5. ser.open()  
  6. serial.read(5)   
更加详细的使用参见其官方文档。

与wxpython的交互

通过上面学习,知道Python与matplotlib交互有三种方式,与GUI交互采用第三种方法面向对象法。 首先知道Matplotlib的常见对象Figure,FigureCanvas,Axes。

需要导入一下几个模块:

[python] view plain copy
  1. from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas  
  2. from matplotlib.figure import Figure  
  3. import numpy as np  

首先简单介绍一下FigureCanvs 这是一个wxWidgets对象,继承自wxPanel,故可以通过其嵌入到wxWidgets应用程序。下面学习一个简单的实例:

[python] view plain copy
  1. from numpy import arange, sin, pi  
  2.   
  3. from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas  
  4. from matplotlib.figure import Figure  
  5. import wx  
  6. class CanvasFrame(wx.Frame):  
  7.   
  8.     def __init__(self):  
  9.         wx.Frame.__init__(self,None,-1,  
  10.                          'CanvasFrame',size=(550,350))  
  11.   
  12.         self.SetBackgroundColour(wx.NamedColor("WHITE"))  
  13.   
  14.         self.figure = Figure()  
  15.         self.axes = self.figure.add_subplot(111)  
  16.         t = arange(0.0,3.0,0.01)  
  17.         s = sin(2*pi*t)  
  18.   
  19.         self.axes.plot(t,s)  
  20.         self.canvas = FigureCanvas(self, -1self.figure)  
  21.         self.sizer = wx.BoxSizer(wx.VERTICAL)  
  22.         self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)  
  23.         self.SetSizer(self.sizer)  
  24.         self.Fit()  
  25.   
  26.   
  27. class App(wx.App):  
  28.   
  29.     def OnInit(self):  
  30.         'Create the main window and insert the custom frame'  
  31.         frame = CanvasFrame()  
  32.         frame.Show(True)  
  33.   
  34.         return True  
  35.   
  36. app = App(0)  
  37. app.MainLoop()  

同笔记1介绍的面向对象方法基本一致,最后将figure加到FigureCanvas上面即可完成图像的绘制。

再前面导入from matplotlib.backends.backend_wx import NavigationToolbar2Wx可以创建导航工具栏,需要添加BoxSizer()对象来控制排版。


原创粉丝点击