使用PyQtChart进行系统资源检测

下载包

python 复制代码
pip install PyQtChart

1. 导入必要的模块

  • sys:用于系统相关的操作,如退出程序时使用。
  • psutil:用于获取系统的性能数据,如 CPU、内存、磁盘、网络流量等。
  • PyQt5.QtWidgets :提供创建 GUI 界面需要的组件,如 QMainWindow, QLabel, QVBoxLayout, QHBoxLayout 等。
  • PyQt5.QtCore :提供核心功能,如定时器 QTimer,以及 Qt 对齐方式。
  • PyQt5.QtChart:用于创建图表并绘制折线图。
  • PyQt5.QtGui :提供图形渲染功能,如 QPainter

2. PerformanceMonitor 类:主窗口

该类继承自 QMainWindow,用于构建应用程序的主窗口,并通过 QChart 来绘制性能数据的折线图。

构造函数 (__init__)
  • 窗口设置:设置窗口标题和大小。
python 复制代码
self.setWindowTitle('电脑性能检测器')
self.setGeometry(100, 100, 800, 600)
  • 标签布局 :创建用于显示 CPU、内存、磁盘、网络流量的标签(QLabel),并将其添加到水平布局(QHBoxLayout)中。
python 复制代码
self.cpu_label = QLabel("CPU使用率: ", self)
self.memory_label = QLabel("内存使用率: ", self)
self.disk_label = QLabel("磁盘使用率: ", self)
self.network_label = QLabel("网络流量: ", self)
  • QtCharts 折线图
  • 创建了一个 QChart 对象,并设置标题为"电脑性能监测"。
  • 创建了 4 条折线(QLineSeries),分别用于显示 CPU、内存、磁盘使用率和网络流量。
  • 添加 X 轴和 Y 轴,X 轴范围为 0-20(表示时间窗口内的点数),Y 轴范围初始设置为 0-100,后续根据数据动态调整。
python 复制代码
self.axis_x = QValueAxis()
self.axis_x.setRange(0, 20)  # 控制 X 轴范围,最大20个点
self.axis_y = QValueAxis()
self.axis_y.setRange(0, 100)  # 初始 Y 轴范围为 0-100
  • 图表布局 :将折线图嵌入到 QChartView 中,并设置抗锯齿效果(QPainter.Antialiasing),然后将图表添加到垂直布局(QVBoxLayout)。
python 复制代码
chart_view.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
  • 数据初始化 :初始化 4 个列表,用于存储实时的 CPU、内存、磁盘和网络流量的数据。设置一个时间窗口(time_window),用于显示最近 20 秒内的数据,current_time 用来跟踪时间。
python 复制代码
self.cpu_data = []
self.memory_data = []
self.disk_data = []
self.network_data = []
self.time_window = 20  # 显示最近 20 秒的数据
  • 定时器 :创建一个定时器 QTimer,每秒钟调用一次 update_performance_data 函数来更新性能数据。
python 复制代码
self.timer = QTimer()
self.timer.setInterval(1000)  # 每秒更新一次
self.timer.timeout.connect(self.update_performance_data)
self.timer.start()

3. update_performance_data 函数:更新性能数据

这是定时器每秒调用的函数,负责获取系统当前的性能数据并更新显示和图表。

  • 获取性能数据

    • 使用 psutil 获取 CPU、内存、磁盘的使用率。
    • 获取当前的网络流量,并计算每秒接收的流量(下载速率),以 KB 为单位显示。
python 复制代码
cpu_usage = psutil.cpu_percent()
memory_usage = psutil.virtual_memory().percent
disk_usage = psutil.disk_usage('/').percent
network_usage = (net_io.bytes_recv - self.prev_net_io.bytes_recv) / 1024
  • 更新标签显示 :将获取的数据更新到对应的 QLabel 上。
python 复制代码
self.cpu_label.setText(f"CPU使用率: {cpu_usage}%")
self.network_label.setText(f"网络流量: {network_usage:.2f} KB/s")
  • 更新数据列表:将最新的性能数据添加到各自的数据列表中,并保证这些列表的长度不超过 20 个数据点(即最多显示 20 秒内的数据)。
python 复制代码
self.cpu_data.append(cpu_usage)
if len(self.cpu_data) > 20:
    self.cpu_data.pop(0)
  • 更新 X 轴范围 :通过 self.axis_x.setRange() 更新 X 轴的范围,使折线图模拟滚动窗口效果,始终显示最新的 20 秒数据。
python 复制代码
self.axis_x.setRange(self.current_time - self.time_window, self.current_time)
  • 动态调整 Y 轴范围:根据当前所有数据的最大值,动态调整 Y 轴范围,确保图表能包含所有数据。
python 复制代码
max_value = max(max(self.cpu_data, default=0), max(self.network_data, default=0))
if max_value > self.axis_y.max():
    self.axis_y.setRange(0, max_value + 10)
  • 更新折线图数据:清空折线图并将新的数据重新绘制到折线图上。
python 复制代码
self.cpu_series.clear()
for i in range(len(self.cpu_data)):
    self.cpu_series.append(self.current_time - len(self.cpu_data) + i, self.cpu_data[i])

4. 主函数

这个函数是程序的入口,创建 QApplication 实例并展示 PerformanceMonitor 窗口:

python 复制代码
def main():
    app = QApplication(sys.argv)
    window = PerformanceMonitor()
    window.show()
    sys.exit(app.exec_())

全部代码

python 复制代码
import sys
import psutil
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QVBoxLayout, QWidget, QLabel
from PyQt5.QtCore import QTimer, Qt
from PyQt5.QtChart import QChart, QChartView, QLineSeries, QValueAxis
from PyQt5.QtGui import QPainter

class PerformanceMonitor(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('电脑性能检测器')
        self.setGeometry(100, 100, 800, 600)

        # 创建布局和控件
        main_layout = QVBoxLayout()  # 主布局垂直排列

        # 创建水平排列的 QLabel
        label_layout = QHBoxLayout()
        self.cpu_label = QLabel("CPU使用率: ", self)
        self.memory_label = QLabel("内存使用率: ", self)
        self.disk_label = QLabel("磁盘使用率: ", self)
        self.network_label = QLabel("网络流量: ", self)

        # 设置 QLabel 的最小高度
        self.cpu_label.setFixedHeight(20)
        self.memory_label.setFixedHeight(20)
        self.disk_label.setFixedHeight(20)
        self.network_label.setFixedHeight(20)

        # 将 QLabel 添加到水平布局中
        label_layout.addWidget(self.cpu_label)
        label_layout.addWidget(self.memory_label)
        label_layout.addWidget(self.disk_label)
        label_layout.addWidget(self.network_label)

        # 将标签布局添加到主布局中
        main_layout.addLayout(label_layout)

        # 创建 QtCharts 的折线图
        self.chart = QChart()
        self.chart.setTitle("电脑性能监测")

        self.cpu_series = QLineSeries(self)
        self.memory_series = QLineSeries(self)
        self.disk_series = QLineSeries(self)
        self.network_series = QLineSeries(self)

        self.cpu_series.setName("CPU 使用率")
        self.memory_series.setName("内存使用率")
        self.disk_series.setName("磁盘使用率")
        self.network_series.setName("网络流量 (KB/s)")

        self.chart.addSeries(self.cpu_series)
        self.chart.addSeries(self.memory_series)
        self.chart.addSeries(self.disk_series)
        self.chart.addSeries(self.network_series)

        # 创建 X 和 Y 轴
        self.axis_x = QValueAxis()
        self.axis_x.setRange(0, 20)  # 控制 X 轴范围,最大20个点
        self.axis_x.setLabelFormat("%d")
        self.axis_x.setTitleText("时间 (s)")
        self.chart.addAxis(self.axis_x, Qt.AlignBottom)

        self.axis_y = QValueAxis()
        self.axis_y.setRange(0, 100)  # 初始 Y 轴范围为 0-100
        self.axis_y.setTitleText("使用率 (%) / 流量 (KB/s)")
        self.chart.addAxis(self.axis_y, Qt.AlignLeft)

        self.cpu_series.attachAxis(self.axis_x)
        self.cpu_series.attachAxis(self.axis_y)

        self.memory_series.attachAxis(self.axis_x)
        self.memory_series.attachAxis(self.axis_y)

        self.disk_series.attachAxis(self.axis_x)
        self.disk_series.attachAxis(self.axis_y)

        self.network_series.attachAxis(self.axis_x)
        self.network_series.attachAxis(self.axis_y)

        # 创建一个 ChartView 将其加入布局
        chart_view = QChartView(self.chart)
        chart_view.setRenderHint(QPainter.Antialiasing)  # 使用 QPainter.Antialiasing
        main_layout.addWidget(chart_view)

        # 创建一个中心窗口来设置布局
        central_widget = QWidget(self)
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        # 初始化数据
        self.cpu_data = []
        self.memory_data = []
        self.disk_data = []
        self.network_data = []

        # X 轴时间滚动窗口
        self.time_window = 20  # 显示最近 20 秒的数据
        self.current_time = 0  # 记录时间

        # 设置定时器
        self.timer = QTimer()
        self.timer.setInterval(1000)  # 每秒更新一次
        self.timer.timeout.connect(self.update_performance_data)
        self.timer.start()

        # 获取初始的网络统计数据
        self.prev_net_io = psutil.net_io_counters()

    # 更新性能数据和曲线图
    def update_performance_data(self):
        # 获取性能数据
        cpu_usage = psutil.cpu_percent()
        memory_usage = psutil.virtual_memory().percent
        disk_usage = psutil.disk_usage('/').percent

        # 获取网络流量
        net_io = psutil.net_io_counters()
        bytes_sent = net_io.bytes_sent - self.prev_net_io.bytes_sent
        bytes_recv = net_io.bytes_recv - self.prev_net_io.bytes_recv
        network_usage = bytes_recv / 1024  # 以 KB 为单位显示下载流量

        self.prev_net_io = net_io  # 更新前一次的网络统计数据

        # 更新显示的文本
        self.cpu_label.setText(f"CPU使用率: {cpu_usage}%")
        self.memory_label.setText(f"内存使用率: {memory_usage}%")
        self.disk_label.setText(f"磁盘使用率: {disk_usage}%")
        self.network_label.setText(f"网络流量: {network_usage:.2f} KB/s")

        # 更新数据
        self.cpu_data.append(cpu_usage)
        self.memory_data.append(memory_usage)
        self.disk_data.append(disk_usage)
        self.network_data.append(network_usage)

        if len(self.cpu_data) > 20:
            self.cpu_data.pop(0)
            self.memory_data.pop(0)
            self.disk_data.pop(0)
            self.network_data.pop(0)

        # 每次添加新的数据后,更新 X 轴范围,模拟滚动窗口
        self.current_time += 1
        self.axis_x.setRange(self.current_time - self.time_window, self.current_time)

        # 找出当前所有数据中的最大值,动态调整 Y 轴范围
        max_value = max(
            max(self.cpu_data, default=0),
            max(self.memory_data, default=0),
            max(self.disk_data, default=0),
            max(self.network_data, default=0)
        )

        # 如果最大值超过当前 Y 轴的范围,动态调整 Y 轴的最大值
        if max_value > self.axis_y.max():
            self.axis_y.setRange(0, max_value + 10)  # 增加10以便有一定的余量

        # 更新折线图的数据
        self.cpu_series.clear()
        self.memory_series.clear()
        self.disk_series.clear()
        self.network_series.clear()

        # 将数据依次填入序列
        for i in range(len(self.cpu_data)):
            self.cpu_series.append(self.current_time - len(self.cpu_data) + i, self.cpu_data[i])
            self.memory_series.append(self.current_time - len(self.memory_data) + i, self.memory_data[i])
            self.disk_series.append(self.current_time - len(self.disk_data) + i, self.disk_data[i])
            self.network_series.append(self.current_time - len(self.network_data) + i, self.network_data[i])

# 主函数
def main():
    app = QApplication(sys.argv)
    window = PerformanceMonitor()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
相关推荐
伍哥的传说7 小时前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
这里有鱼汤7 小时前
Python量化实盘踩坑指南:分钟K线没处理好,小心直接亏钱!
后端·python·程序员
小莞尔8 小时前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
大模型真好玩8 小时前
深入浅出LangGraph AI Agent智能体开发教程(五)—LangGraph 数据分析助手智能体项目实战
人工智能·python·mcp
测试老哥8 小时前
Selenium 使用指南
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
我是菜鸟0713号8 小时前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_8 小时前
QT(4)
开发语言·汇编·c++·qt·算法
Brookty8 小时前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
百锦再8 小时前
[特殊字符] Python在CentOS系统执行深度指南
开发语言·python·plotly·django·centos·virtualenv·pygame
Anson Jiang8 小时前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件