我有一个处理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 time
class 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数据的动态更新。其他详细的解释见文中的注释部分。
-
- import wx
- from matplotlib.figure import Figure
- import matplotlib.font_manager as font_manager
- import numpy as np
- from matplotlib.backends.backend_wxagg import \
- FigureCanvasWxAgg as FigureCanvas
-
- TIMER_ID = wx.NewId()
-
- POINTS = 300
-
- class PlotFigure(wx.Frame):
-
- def __init__(self):
- wx.Frame.__init__(self, None, wx.ID_ANY, title="CPU Usage Monitor", size=(600, 400))
-
- self.fig = Figure((6, 4), 100)
-
- self.canvas = FigureCanvas(self, wx.ID_ANY, self.fig)
-
- self.ax = self.fig.add_subplot(111)
-
- self.ax.set_ylim([0, 100])
- self.ax.set_xlim([0, POINTS])
-
- self.ax.set_autoscale_on(False)
- self.ax.set_xticks([])
-
- self.ax.set_yticks(range(0, 101, 10))
-
-
- self.ax.grid(True)
-
- self.user = [None] * POINTS
- self.l_user,=self.ax.plot(range(POINTS),self.user,label='User %')
-
-
- self.ax.legend(loc='upper center',
- ncol=4,
- prop=font_manager.FontProperties(size=10))
-
-
- self.canvas.draw()
-
-
- self.bg = self.canvas.copy_from_bbox(self.ax.bbox)
-
-
- wx.EVT_TIMER(self, TIMER_ID, self.onTimer)
-
- def onTimer(self, evt):
-
-
- self.canvas.restore_region(self.bg)
-
- temp =np.random.randint(10,80)
- self.user = self.user[1:] + [temp]
-
- self.l_user.set_ydata(self.user)
-
- self.ax.draw_artist(self.l_user)
- self.canvas.blit(self.ax.bbox)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- frame = PlotFigure()
- t = wx.Timer(frame, TIMER_ID)
- t.Start(50)
- frame.Show()
- app.MainLoop()
运行结果如下所示:
但程序运行在关闭的时候会出现应用程序错误,不知道什么问题。python不是有垃圾回收机制吗,难道是内存泄露?
猜测的原因可能是在关闭的时候正在绘图故导致应用程序出错。通过添加Frame的析构函数,停止更新则不会出现问题。
- def __del__( self ):
- t.Stop()
python 学习之读串口
Python中用于读串口的模块是 pySerial,使用非常的方便,可以从http://pypi.python.org/pypi/pyserial下载其安装包。
读取串口时首先导入包 import serial,其次设置读取哪一个口、波特率、数据位、停止位。
serial的原型如下:
- class serial.Serial
-
- __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)
简单的实例如下:
- import serial
- ser = serial.Serial()
- ser.baudrate = 19200
- ser.port = 0
- ser.open()
- serial.read(5)
更加详细的使用参见其官方文档。
与wxpython的交互
通过上面学习,知道Python与matplotlib交互有三种方式,与GUI交互采用第三种方法面向对象法。 首先知道Matplotlib的常见对象Figure,FigureCanvas,Axes。
需要导入一下几个模块:
- from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
- from matplotlib.figure import Figure
- import numpy as np
首先简单介绍一下FigureCanvs 这是一个wxWidgets对象,继承自wxPanel,故可以通过其嵌入到wxWidgets应用程序。下面学习一个简单的实例:
- from numpy import arange, sin, pi
-
- from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
- from matplotlib.figure import Figure
- import wx
- class CanvasFrame(wx.Frame):
-
- def __init__(self):
- wx.Frame.__init__(self,None,-1,
- 'CanvasFrame',size=(550,350))
-
- self.SetBackgroundColour(wx.NamedColor("WHITE"))
-
- self.figure = Figure()
- self.axes = self.figure.add_subplot(111)
- t = arange(0.0,3.0,0.01)
- s = sin(2*pi*t)
-
- self.axes.plot(t,s)
- self.canvas = FigureCanvas(self, -1, self.figure)
- self.sizer = wx.BoxSizer(wx.VERTICAL)
- self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
- self.SetSizer(self.sizer)
- self.Fit()
-
-
- class App(wx.App):
-
- def OnInit(self):
- 'Create the main window and insert the custom frame'
- frame = CanvasFrame()
- frame.Show(True)
-
- return True
-
- app = App(0)
- app.MainLoop()
同笔记1介绍的面向对象方法基本一致,最后将figure加到FigureCanvas上面即可完成图像的绘制。
再前面导入from matplotlib.backends.backend_wx import NavigationToolbar2Wx可以创建导航工具栏,需要添加BoxSizer()对象来控制排版。