pyside6实时更新折线图
import sys
import random
from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
from PySide6.QtCore import Qt, QPointF, QRectF, QTimer
from PySide6.QtGui import QPainter, QPen, QColor, QFont
# 可滚动的线图类,用于显示数据序列
# 定义一个可滚动的线图类
class ScrollableLineGraph(QGraphicsItem):
def __init__(self, data):
"""
初始化线图项,设置初始显示范围和数据
:param data: 要显示的数据列表
"""
super().__init__()
self.data = data
self.current_start = 0 # 当前显示的起始索引
self.bounding_rect = QRectF(0, 0, 600, 450) # 线图的边界矩形
def boundingRect(self):
"""
返回线图的边界矩形,用于确定绘制区域
:return: 矩形边界
"""
return self.bounding_rect
def paint(self, painter, option, widget):
"""
绘制线图,包括坐标轴、刻度和数据线
:param painter: 绘制工具
:param option: 绘制选项
:param widget: 关联的窗口部件
"""
painter.setRenderHint(QPainter.Antialiasing) # 开启抗锯齿
axis_pen = QPen(QColor(128, 128, 128)) # 坐标轴线颜色
line_pen = QPen(QColor(0, 200, 100)) # 数据线颜色
text_font = QFont() # 字体设置
# 绘制x轴
painter.setPen(axis_pen)
painter.drawLine(0, 450, 600, 450)
# 绘制x轴刻度和标签
for i in range(0, 50, 5):
x = (i - self.current_start) * 12
if 0 <= x < 600:
painter.drawLine(x, 450, x, 455)
painter.drawText(x - 5, 465, str(i + self.current_start))
# 绘制y轴
painter.drawLine(0, 0, 0, 450)
# # 绘制y轴刻度和标签
# for i in range(0, 11):
# y = 450 - 45 * i
# painter.drawLine(-5, y, 0, y)
# painter.drawText(-20, y - 5, str(i * 10))
# # 绘制y轴刻度和标签,给每个标签添加上横向网格,网格为点状虚线
# for i in range(0, 11):
# y = 450 - 45 * i
# # 网格为点状虚线
# painter.setPen(QPen(QColor(128, 128, 128), 0.5, Qt.DashLine))
# painter.drawLine(-5, y, 0, y)
# painter.drawText(-20, y - 5, str(i * 10))
# painter.drawLine(0, y, 600, y)
# 假设已经初始化了painter对象等必要的准备工作
# 定义一些常量,提高代码的可读性
CANVAS_HEIGHT = 450
SCALE_FACTOR = 45
LABEL_OFFSET = -20
GRID_LINE_WIDTH = 0.5
GRID_LINE_COLOR = QColor(128, 128, 128)
GRID_LINE_STYLE = Qt.DashLine
MAX_LABELS = 10
# 新增:封装绘制网格线和刻度标签的函数
def draw_scale_and_grid(painter, y_position, label):
"""
绘制y轴刻度和标签以及对应的横向网格线
:param painter: QPainter对象,用于绘制
:param y_position: y轴位置
:param label: 刻度标签的文本
"""
try:
# 绘制网格线
painter.setPen(QPen(GRID_LINE_COLOR, GRID_LINE_WIDTH, GRID_LINE_STYLE))
painter.drawLine(-5, y_position, 0, y_position)
# 绘制刻度标签
painter.drawText(-LABEL_OFFSET, y_position - 5, label)
# 绘制右侧网格线
painter.drawLine(0, y_position, 600, y_position)
except Exception as e:
print(f"Error during drawing scale and grid: {e}")
# 主绘制逻辑
try:
for i in range(MAX_LABELS + 1): # 由于范围是从0到10,因此循环次数应为MAX_LABELS + 1
y = CANVAS_HEIGHT - SCALE_FACTOR * i
# 检查y位置是否在画布内,若不在则跳过
if y < 0:
break
label = str(i * 10)
draw_scale_and_grid(painter, y, label)
except Exception as e:
print(f"Unexpected error occurred: {e}")
# 假设在这段代码的末尾,有适当的资源释放逻辑,例如painter对象的销毁等
# 设置字体
painter.setFont(text_font)
# 绘制x轴和y轴标签
painter.drawText(610, 460, "Time")
painter.rotate(-90)
painter.drawText(-10, 10, "Value")
painter.rotate(90)
# 绘制数据线
painter.setPen(line_pen)
painter.setRenderHint(QPainter.SmoothPixmapTransform)
last_point = QPointF(0, 450 - self.data[self.current_start])
for i in range(self.current_start, min(self.current_start + 50, len(self.data))):
x = (i - self.current_start) * 12
y = 450 - self.data[i]
painter.drawLine(last_point, QPointF(x, y))
last_point = QPointF(x, y)
def scroll_right(self):
"""
向右滚动线图,显示新的数据
"""
self.current_start = min(len(self.data) - 50, self.current_start + 1)
self.update()
def scroll_left(self):
"""
向左滚动线图,显示之前的数据
"""
self.current_start = max(0, self.current_start - 1)
self.update()
# 线图视图类,用于显示和交互
# 定义线图视图类
class LineGraphView(QGraphicsView):
def __init__(self, data):
"""
初始化线图视图,设置场景和初始数据
:param data: 要显示的数据列表
"""
super().__init__()
self.scene = QGraphicsScene(self)
self.setScene(self.scene)
self.data_graph = ScrollableLineGraph(data)
self.scene.addItem(self.data_graph)
self.setRenderHint(QPainter.Antialiasing)
self.setFixedSize(800, 600)
self.setSceneRect(0, 0, 600, 450)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
# 设置定时器,用于动态更新数据
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_data)
self.timer.start(500) # 每500毫秒触发一次
def update_data(self):
"""
更新线图数据,添加新数据并滚动显示
"""
new_data = random.randint(0, 400)
self.data_graph.data.append(new_data)
self.data_graph.current_start = max(0, len(self.data_graph.data) - 50)
self.data_graph.update()
def wheelEvent(self, event):
"""
处理鼠标滚轮事件,用于滚动线图
:param event: 鼠标事件
"""
super().wheelEvent(event)
if event.angleDelta().y() > 0:
self.data_graph.scroll_left()
else:
self.data_graph.scroll_right()
if __name__ == "__main__":
app = QApplication(sys.argv)
data = [random.randint(0, 0) for _ in range(100)] # 生成测试数据
graph_view = LineGraphView(data)
graph_view.show()
sys.exit(app.exec())