之前一直用爬虫捉取路由实时上下载的记录用数据库保存,有时可用matplotlib来查看时间与上下传的曲线图,但是静态的,查询的时间段需自行认定,虽然qt的日历类可以比较方便取日期按日期查,但总觉要点有点麻烦,又不想看24小时的数据,截取最近几小时观看数据并实时展示应该是很好的方式,经百度发现pyqt有个很方便的库来展示动态数据,这个库是pyqtchart,安装PyQt时并没有这个库的,需另行安装,pip install pyqtchart安装就可以了,下面就结合代码和实际情况记录一下。
import sqlite3,sys,time
from datetime import datetime
from PyQt5.QtChart import QDateTimeAxis,QValueAxis,QSplineSeries,QChart,QChartView
from PyQt5.QtWidgets import QApplication
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import QDateTime,Qt,QTimer
class ChartView(QChartView,QChart): #原代码如此,继承了两个类,其实去掉QChart也没影响
def __init__(self, *args, **kwargs):
super(ChartView, self).__init__(*args, **kwargs)
self.connect = sqlite3.connect("netdata.db") #数据库,表名为t1,包括时间(年月日时分秒的方式,用sqlite的自动时间截生成的,为方便自己看,转成年月日,结果是个坑),下载速度,上传速度
self.resize(1500, 500)
self.setRenderHint(QPainter.Antialiasing) # 抗锯齿,注释此行曲线很难看
self.limitminute=240 #设置显示多少分钟内的活动
self.maxspeed = 300 #预设y轴最大值
self.chart_init()
self.timer_init()
def timer_init(self):
#使用QTimer,2秒触发一次,更新数据
self.timer = QTimer(self)
self.timer.timeout.connect(self.drawLine)
self.timer.start(2000)
def chart_init(self):
self.chart = QChart()
self.series = QSplineSeries() #这个是平滑曲线类,而QSplineSeries()是折线类,根所自己需求选用,下载数据曲线
self.series_upload = QSplineSeries() #上传数据曲线
#设置曲线名称
self.series.setName("下载速度")
self.series_upload.setName('上传速度')
#把曲线添加到QChart的实例中
self.chart.addSeries(self.series)
self.chart.addSeries(self.series_upload)
#声明并初始化X轴,Y轴
self.dtaxisX = QDateTimeAxis()
self.vlaxisY = QValueAxis()
#设置坐标轴显示范围
self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-self.limitminute*60))
self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0))
self.vlaxisY.setMin(0)
self.vlaxisY.setMax(self.maxspeed) #设置y轴最大值
#设置X轴时间样式
self.dtaxisX.setFormat("hh:mm") #关注就是几小时内的数据,就留时分好了
#设置坐标轴上的格点
self.dtaxisX.setTickCount(15) #平均分的刻度分隔
self.vlaxisY.setTickCount(10)
#设置坐标轴名称
self.dtaxisX.setTitleText("时间")
self.vlaxisY.setTitleText("速度(M)")
#设置网格显示,并设为灰色
self.vlaxisY.setGridLineVisible(True)
self.vlaxisY.setGridLineColor(Qt.gray)
self.dtaxisX.setGridLineVisible(True)
self.dtaxisX.setGridLineColor(Qt.gray)
#把坐标轴添加到chart中
self.chart.addAxis(self.dtaxisX,Qt.AlignBottom)
self.chart.addAxis(self.vlaxisY,Qt.AlignLeft)
#把曲线关联到坐标轴
self.series.attachAxis(self.dtaxisX)
self.series.attachAxis(self.vlaxisY)
self.series_upload.attachAxis(self.dtaxisX)
self.series_upload.attachAxis(self.vlaxisY)
self.setChart(self.chart)
def drawLine(self):
#获取当前时间
bjtime = QDateTime.currentDateTime()
#更新X轴坐标
self.dtaxisX.setMin(bjtime.addSecs(-self.limitminute*60))
self.dtaxisX.setMax(bjtime.addSecs(0))
#设Y轴最大值,查询数据库最近4小时内的下载最大值,并乘1.2作为y轴最大值
for xx in self.connect.execute(
"select max(downdata) from t1 where time > datetime('now','-4 hour','localtime') order by time"):
if xx:
self.vlaxisY.setMax(int(xx[0] * 1.2))
else:
self.vlaxisY.setMax(self.maxspeed)
if self.series.at(0): #self.serie存在索引0时,也就是起码有一个数据对过旧数据进行清除,self.series.removePoints两参数一个是索引,一个是从索引起始删除多少个数值,两条数据均如此处理
if self.series.at(0).x()<bjtime.addSecs(-self.limitminute*60).toMSecsSinceEpoch(): #self.series.at(0).x()其实就是图像x坐标值,与原始数据可能并不完全相等,小数点后的值是约去了的,bjtime的toMSecsSinceEpoch()其实与time.time()相约,不过前者是整数,是后者的1000倍,所以后面需要转换
self.series.removePoints(0, 1)
if self.series_upload.at(0):
if self.series_upload.at(0).x()<bjtime.addSecs(-self.limitminute*60).toMSecsSinceEpoch():
self.series_upload.removePoints(0, 1)
for xx in self.connect.execute("select * from t1 order by time desc limit 1"):
#x1 = self.connect.execute("select strftime('%s',?)", (xx[0],)).fetchone()[0] #用此法转出来的时间截与time.time()整好差8个时区,用sqlite不知如何处理了
x1=time.mktime(datetime.strptime(xx[0], '%Y-%m-%d %H:%M:%S').timetuple()) #用py内置库的办法有日期转为时间截
x_time=int(x1)*1000 #再乘1000,以符号格式要求
y0_value=xx[1] #取得下载数据
y1_value=xx[2] #取得上传数据
#添加数据到曲线末端
if self.series.at(0): #因数据库并非每秒更新,为免相同数据重复录入,先判断self.series起码有一个数据
if x_time!=self.series.at(self.series.count()-1).x(): #假如最新的时间轴与数据库取得的不一致就录入,相同就跳过
self.series.append(x_time, y0_value)
else: #当self.series为空时起码录入第一个数据,下面另外一轴同样处理
self.series.append(x_time,y0_value)
if self.series_upload.at(0):
if x_time!=self.series_upload.at(self.series_upload.count()-1).x():
self.series_upload.append(x_time, y1_value)
else:
self.series_upload.append(x_time,y1_value)
#print(self.series.count(),self.series_upload.count())
if __name__ == "__main__":
app = QApplication(sys.argv)
view = ChartView()
view.show()
sys.exit(app.exec_())