之前一直用爬蟲捉取路由實時上下載的記錄用數據庫保存,有時可用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_())