前言
前置工作都在上文的博客裏邊說過了,鏈接如下:PyQt5:QChart繪製折線圖(1)
,在這邊文章裏邊直接說繪製動態折線相關了。
Charts相關刷新函數
1.append()
Qt官方解釋:
append(qreal x, qreal y):Adds the data point with the coordinates x and y to the series.
append(const QPointF &point):This is an overloaded function.Adds the data point point to the series.
append(const QList<QPointF> &points):This is an overloaded function.Adds the list of data points specified by points to the series.
將點的座標信息或者說數據添加到series中,我的理解爲追加。
2.replace()
Qt官方解釋:
replace(qreal oldX, qreal oldY, qreal newX, qreal newY):Replaces the point with the coordinates oldX and oldY with the point with the coordinates newX and newY. Does nothing if the old point does not exist.
replace(const QPointF &oldPoint, const QPointF &newPoint):Replaces the point specified by oldPoint with the one specified by newPoint.
replace(int index, qreal newX, qreal newY):Replaces the point at the position specified by index with the point that has the coordinates newX and newY.
replace(int index, const QPointF &newPoint):Replaces the point at the position specified by index with the point specified by newPoint.
replace(QList<QPointF> points):Replaces the current points with the points specified by points
replace(QVector<QPointF> points):Replaces the current points with the points specified by points.
字面意思替換,單個座標點的替換,組座標數據替換等,在下文我用的是List,羣組替換。
思路
將思路主要拆解爲3個部分:數據源,座標列表更新,折線圖的刷新
1.數據源:可以爲外部實時動態數據,或者是內部動態計算產生的數據。這裏我隨機造了一些動態數據。
2.座標列表更新:在我的折線圖中,座標設置了固定顯示6個點,這裏可以自己隨意,或者將x軸更新爲時間軸,就爲實時數據了。在迭代更新中,定時器檢測源數據大於0,就可以更新數據,
3.座標軸刷新:採用了 replace()函數,替換。
源碼
1.數據源
import random
DataVector = []
mutex = QMutex()
class ThreadCtl(QThread):
def __init__(self):
super().__init__()
self.threadstatus = 1
def run(self):
while self.threadstatus == 1:
#產生隨機數據值,座標點 y值
self.randdata_h = random.uniform(1, 6)
self.randdata_h = round(self.randdata_h, 2)
# self.randdata_w = random.uniform(1, 6)
# self.randdata_w = round(self.randdata_w, 2)
# self.points = [self.post,self.randdata_h,]
#休眠1S
time.sleep(1)
#加鎖,插入數據,解鎖
mutex.lock()
DataVector.append(self.randdata_h)
mutex.unlock()
print("DataVector:",DataVector)
採用多線程方式,繼承QThread 類,定時產生數據,數據爲:1~6,小數點後兩位的float數據。
DataVector 一個list容器,用來存儲數據列表。
加一把資源鎖,防止對DataVector讀寫造成的資源搶佔問題。
2.座標列表更新
#定時器
self.timer = QTimer()
self.timer.timeout.connect(self.update)
self.timer.start(2000)
def update(self):
if len(DataVector) > 0 :
#取出第一位數據,加鎖,解鎖
mutex.lock()
self.value = DataVector[0]
DataVector.pop(0)
mutex.unlock()
#刪除最後一個座標點
del self._1_point_list[len(self._1_point_list)-1]
#第一位插入座標點
self._1_point_list.insert(0,QPointF(0,self.value))
#更新x座標點值
for i in range(0,len(self._1_point_list)):
self._1_point_list[i].setX(i)
採用定時器方式,定時去讀取DataVector 列表,列表數據大於0就去取出第一位數據。
self._1_point_list 座標點列表更新規則,最後一位刪掉,剩下的前幾位向後移位一位,第一位填入DataVector 列表取出的第一位數據。
採用 insert函數,在第一位插入,後續相當於自動移位。然後橫座標更新。
3.折線更新
for i in range(0,len(self._1_point_list)):
self._1_point_list[i].setX(i)
#replace更新折線圖
self.series_1.replace(self._1_point_list)
引申
在實際的項目使用中,數據源的獲取,如果是實時數據,如果數據更新速度較快,應該採用什麼方式?,如果數據量很大應該採用什麼方式?,折線圖刷新時有什麼要求? ,隊列積壓,應該採用什麼方式來處理
我上述採用的方法是,多線程,子線程處理數據源,主線程定時器方式,處理折線圖。
實際使用中,數據源處理,座標列表更新,界面折線圖刷新,都有實際的問題。每一個過程,都單獨做一個線程來處理,給不同的數據量,設置不同的閾值,對應不同的更新速度,刷新速度。檢測到數據積壓,就去提高座標列表更新的處理速度,爲了減小,界面折線圖刷新的處理壓力,將座標列表也改爲座標點List,改爲List[[],[]]模式,設置好界面更新時,直接調用提前處理好的座標更新,加快刷新速度
實際還有一次刷新大批量數據時,應該怎麼處理的問題?這一塊暫沒有碰到,隨後寫的時候在處理一下。