我正在流式传输我想要有效绘制图表的时间序列(在小型计算机上实时显示 20 多个图表)。我已经在 PyQt5 上尝试过 PyQtChart 和 pyqtgraph,但是对于这两个库,我最终会为收到的每个数据重新绘制整个图表,这感觉不是最佳的。我选择了 PyQtChart,因为它可以处理更好的 DatetimeSeries,但很高兴被证明是错误的(并分享 pyqtgraph 代码,只是不想让帖子太大)。
Bellow 是我使用 PyQtChart 使用随机数据的工作代码,以便您可以运行它:
import sys
from random import randint
from typing import Union
from PyQt5.QtChart import (QChart, QChartView, QLineSeries, QDateTimeAxis, QValueAxis)
from PyQt5.QtCore import Qt, QDateTime, QTimer
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import (QWidget, QGridLayout)
class Window(QWidget):
def __init__(self, window_name: str = 'Ticker'):
QWidget.__init__(self)
# GUI
self.setGeometry(200, 200, 600, 400)
self.window_name: str = window_name
self.setWindowTitle(self.window_name)
layout = QGridLayout(self)
# change the color of the window
self.setStyleSheet('background-color:black')
# Series
self.high_dataset = QLineSeries()
self.low_dataset = QLineSeries()
self.mid_dataset = QLineSeries()
self.low_of_day: Union[float, None] = 5
self.high_of_day: Union[float, None] = 15
# Y Axis
self.time_axis_y = QValueAxis()
self.time_axis_y.setLabelFormat("%.2f")
self.time_axis_y.setTitleText("Price")
# X Axis
self.time_axis_x = QDateTimeAxis()
self.time_axis_x.setFormat("hh:mm:ss")
self.time_axis_x.setTitleText("Datetime")
# Events
self.qt_timer = QTimer()
# QChart
self.chart = QChart()
self.chart.addSeries(self.mid_dataset)
self.chart.addSeries(self.high_dataset)
self.chart.addSeries(self.low_dataset)
self.chart.setTitle("Barchart Percent Example")
self.chart.setTheme(QChart.ChartThemeDark)
# https://linuxtut.com/fr/35fb93c7ca35f9665d9f/
self.chart.legend().setVisible(True)
self.chart.legend().setAlignment(Qt.AlignBottom)
self.chartview = QChartView(self.chart)
# using -1 to span through all rows available in the window
layout.addWidget(self.chartview, 2, 0, -1, 3)
self.chartview.setChart(self.chart)
def set_yaxis(self):
# Y Axis Settings
self.time_axis_y.setRange(int(self.low_of_day * .9), int(self.high_of_day * 1.1))
self.chart.addAxis(self.time_axis_y, Qt.AlignLeft)
self.mid_dataset.attachAxis(self.time_axis_y)
self.high_dataset.attachAxis(self.time_axis_y)
self.low_dataset.attachAxis(self.time_axis_y)
def set_xaxis(self):
# X Axis Settings
self.chart.removeAxis(self.time_axis_x)
self.time_axis_x = QDateTimeAxis()
self.time_axis_x.setFormat("hh:mm:ss")
self.time_axis_x.setTitleText("Datetime")
self.chart.addAxis(self.time_axis_x, Qt.AlignBottom)
self.mid_dataset.attachAxis(self.time_axis_x)
self.high_dataset.attachAxis(self.time_axis_x)
self.low_dataset.attachAxis(self.time_axis_x)
def start_app(self):
self.qt_timer.timeout.connect(self.retrieveStream, )
time_to_wait: int = 500 # milliseconds
self.qt_timer.start(time_to_wait)
def retrieveStream(self):
date_px = QDateTime()
date_px = date_px.currentDateTime().toMSecsSinceEpoch()
print(date_px)
mid_px = randint(int((self.low_of_day + 2) * 100), int((self.high_of_day - 2) * 100)) / 100
self.mid_dataset.append(date_px, mid_px)
self.low_dataset.append(date_px, self.low_of_day)
self.high_dataset.append(date_px, self.high_of_day)
print(f"epoch: {date_px}, mid: {mid_px:.2f}")
self.update()
def update(self):
print("updating chart")
self.chart.removeSeries(self.mid_dataset)
self.chart.removeSeries(self.low_dataset)
self.chart.removeSeries(self.high_dataset)
self.chart.addSeries(self.mid_dataset)
self.chart.addSeries(self.high_dataset)
self.chart.addSeries(self.low_dataset)
self.set_yaxis()
self.set_xaxis()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
window.start_app()
sys.exit(app.exec_())
这段代码最大的担忧是:
- 基本上重新绘制图表的每个元素的“更新”方法=>我更喜欢双端队列,刷新/更新/重新启动类型的解决方案
- QLineSeries 似乎没有像双端队列那样的 maxLen 集合,所以我最终可能会得到大量数据(理想情况下希望运行三个以上的 QLineSeries)
除此之外,我将很高兴收到有关如何优化此代码的任何见解。我是 Qt/Asyncio/Threading 的新手,并且非常渴望学习。
最好的