自学内容网 自学内容网

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)!