pyside6中使用matplotlib画折线图
pyside6中使用matplotlib画折线图
import sys
import time
import random
import numpy as np
from datetime import datetime, timedelta
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PySide6.QtCore import QTimer
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg, NavigationToolbar2QT
from matplotlib.figure import Figure
from matplotlib.widgets import SpanSelector
from matplotlib.dates import date2num, num2date, DateFormatter
import matplotlib.pyplot as plt
# 设置字体为SimHei显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 设置正常显示符号
plt.rcParams['axes.unicode_minus']=False
class DynamicPlot(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super().__init__(fig)
self.xdata, self.ydata = [], []
self.line = None
self.timer = QTimer()
self.timer.timeout.connect(self.update_plot)
self.timer.start(1000)
self.axes.grid(True, linestyle=':')
self.axes.set_xlabel('Time')
self.axes.set_ylabel('Value')
# 设置x轴为日期格式,并指定日期格式化器
self.axes.xaxis_date()
self.axes.xaxis.set_major_formatter(DateFormatter('%H:%M:%S'))
self.axes.fmt_xdata = DateFormatter('%H:%M:%S')
# 假设第一个数据点的时间为start_time
start_time = self.xdata[0] if self.xdata else datetime.now()
# 在数据序列开始之前添加一个(0,0)的点
self.xdata.insert(0, start_time - timedelta(seconds=1))
self.ydata.insert(0, 0)
# 设置x轴的初始范围,确保包含(0,0)点
self.axes.set_xlim(start_time - timedelta(seconds=1), start_time + timedelta(hours=1))
# 设置y轴的初始范围,确保包含0
self.axes.set_ylim(0, max(self.ydata) if self.ydata else 200)
# 初始化时设置坐标轴范围
self.axes.set_xlim(datetime.min, datetime.min + timedelta(minutes=1))
self.axes.set_ylim(0, 200)
self.line, = self.axes.plot([], [], 'o-', lw=1, ms=2)
self.span = SpanSelector(self.axes, self.onselect, 'horizontal', useblit=True,
props=dict(alpha=0.5, facecolor='red'),
interactive=True, drag_from_anywhere=True)
# 标记坐标轴范围已设置的标志
self.xlim_set = False
def update_plot(self):
current_time = datetime.now()
if len(self.ydata) < 20:
self.xdata.append(current_time)
self.ydata.append(random.randint(0, 200))
self.line.set_data(self.xdata, self.ydata)
# 确保x轴的范围至少包含(0,0)点
self.axes.set_xlim(self.xdata[0], self.xdata[-1])
# 确保y轴的范围包含0
self.axes.set_ylim(0, max(self.ydata) if self.ydata else 200)
# 如果是第一次添加数据点,设置坐标轴范围
if not self.xlim_set:
self.axes.set_xlim(self.xdata[0], self.xdata[-1])
self.axes.set_ylim(0, max(self.ydata))
self.xlim_set = True
# 每次更新数据后,重新计算轴的极限并重新缩放视图
self.axes.relim()
self.axes.autoscale_view()
self.draw()
def onselect(self, xmin, xmax):
xdata = np.array(self.xdata)
ydata = np.array(self.ydata)
xdata_numeric = date2num(xdata)
indmin, indmax = np.searchsorted(xdata_numeric, (xmin, xmax))
indmax = min(len(xdata) - 1, int(indmax))
region_x = xdata[indmin:indmax]
region_y = ydata[indmin:indmax]
if len(region_y) == 0:
print("No data selected.")
return
min_val = np.min(region_y)
max_val = np.max(region_y)
avg_val = np.mean(region_y)
cumsum_val = np.sum(region_y)
mid_index = (indmin + indmax) // 2
# 确保mid_index在有效范围内
if mid_index >= len(region_x):
mid_index = len(region_x) - 1
mid_x = region_x[mid_index]
for txt in self.axes.texts:
txt.remove()
self.axes.text(mid_x, max_val, f"最大: {max_val:.9f}\n最小: {min_val:.9f}\n平均: {avg_val:.9f}\n总和: {cumsum_val:.9f}",
transform=self.axes.transData, fontsize=8,
verticalalignment='top', bbox=dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9))
self.draw_idle()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
dp = DynamicPlot(self, width=5, height=4, dpi=100)
layout = QVBoxLayout()
layout.addWidget(dp)
toolbar = NavigationToolbar2QT(dp, self)
layout.addWidget(toolbar)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
原文地址:https://blog.csdn.net/hyd_csdn/article/details/140697023
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!