qt使用QCustomplot绘制cpu和内存使用率图

一、QCustomPlot介绍

            QCustomPlot是一个开源的Qt C++图表库,用于可视化数据。该库提供了多种类型的可定制的图表,包括散点图、线图、柱状图和等高线图等。它还支持自定义绘制,可以创建任意形状和大小的元素,并使其与其他元素交互。QCustomPlot易于集成到现有的Qt应用程序中,支持像鼠标选择、缩放和平移这样的常用图表交互。此外,它还可以生成高质量的图像和PDF输出。QCustomplot的文档详细地介绍了其使用方法和API,对于需要在其应用程序中添加数据可视化功能的开发人员来说,是一个强大而方便的工具。

二、界面预览

在这里插入图片描述

三、代码实现

1、Qcustomplot下载

您可以从QCustomPlot官网(https://www.qcustomplot.com/index.php/download)下载QCustomPlot。在该网站上,您可以找到最新的稳定版本以及所有历史版本的下载链接。
在这里插入图片描述

2、将Qcustomplot添加到你的工程

解压下载的Qcustomplot压缩包,然后将qcustomplot.cppqcustomplot.h拷贝到你的工程
在这里插入图片描述
然后工程右键->添加现有文件到你的工程中。
在这里插入图片描述

3、工程文件修改

打开工程.pro文件,添加printsupport组件支持。
注意:如果你的编译器的版本是6.5,还需要添加QMAKE_CXXFLAGS += -Wa,-mbig-obj,这句,如下
在这里插入图片描述

4、代码编写

a、新建类

首先新建一个设计师界面类,然后在设计师界面中放置一个widget,然后提升为QCustomPlot,如下:
在这里插入图片描述

四、工程源码

.h文件

#ifndef SYSTEMSTATISTICSWIDGET_H
#define SYSTEMSTATISTICSWIDGET_H#include <QWidget>
#include <QPixmap>
#include <QTextEdit>
#include <QObject>
#include <QTextObjectInterface>
#include <QPicture>
#include <QVariant>
#include <QPainter>#include "qcustomplot.h"namespace Ui {
class SystemStatisticsWidget;
}class AxisTag : public QObject
{
public:explicit AxisTag(QCPAxis *parentAxis):QObject(parentAxis),mAxis(parentAxis){mDummyTracer = new QCPItemTracer(mAxis->parentPlot());mDummyTracer->setVisible(false);mDummyTracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);mDummyTracer->position->setTypeY(QCPItemPosition::ptPlotCoords);mDummyTracer->position->setAxisRect(mAxis->axisRect());mDummyTracer->position->setAxes(0, mAxis);mDummyTracer->position->setCoords(1, 0);mArrow = new QCPItemLine(mAxis->parentPlot());mArrow->setLayer("overlay");mArrow->setClipToAxisRect(false);mArrow->setHead(QCPLineEnding::esSpikeArrow);mArrow->end->setParentAnchor(mDummyTracer->position);mArrow->start->setParentAnchor(mArrow->end);mArrow->start->setCoords(15, 0);mLabel = new QCPItemText(mAxis->parentPlot());mLabel->setLayer("overlay");mLabel->setClipToAxisRect(false);mLabel->setPadding(QMargins(3, 0, 3, 0));mLabel->setBrush(QBrush(Qt::white));mLabel->setPen(QPen(Qt::blue));mLabel->setPositionAlignment(Qt::AlignLeft|Qt::AlignVCenter);mLabel->position->setParentAnchor(mArrow->start);}virtual ~AxisTag(){if (mDummyTracer)mDummyTracer->parentPlot()->removeItem(mDummyTracer);if (mArrow)mArrow->parentPlot()->removeItem(mArrow);if (mLabel)mLabel->parentPlot()->removeItem(mLabel);}// setters:void setPen(const QPen &pen){mArrow->setPen(pen);mLabel->setPen(pen);}void setBrush(const QBrush &brush){mLabel->setBrush(brush);}void setText(const QString &text){mLabel->setText(text);}// getters:QPen pen() const { return mLabel->pen(); }QBrush brush() const { return mLabel->brush(); }QString text() const { return mLabel->text(); }// other methods:void updatePosition(double value){mDummyTracer->position->setCoords(1, value);mArrow->end->setCoords(mAxis->offset(), 0);}protected:QCPAxis *mAxis;QPointer<QCPItemTracer> mDummyTracer;QPointer<QCPItemLine> mArrow;QPointer<QCPItemText> mLabel;
};class SystemStatisticsWidget : public QWidget
{Q_OBJECTpublic:enum {PlotTextFormat = QTextFormat::UserObject + 3902};enum {PicturePropertyId = 1};explicit SystemStatisticsWidget(QWidget *parent = nullptr);~SystemStatisticsWidget();void addData(double cpuUsage,double memoryUsage);void popWindow(int x,int y,int width,int height);
protected:void showEvent(QShowEvent *event) override;
private:void controlInit();void setLabelText(double cpuUsage,double memoryUsage);
private slots:void btnClickedSlot();
private:Ui::SystemStatisticsWidget *ui;QPointer<QCPGraph> graphCpu;QPointer<QCPGraph> graphMemory;AxisTag *tagCpu;AxisTag *tagMemory;QString filePath;
};#endif // SYSTEMSTATISTICSWIDGET_H

AxisTag 类是图像右边的那个小标签,用于显示单前值。
.cpp文件:

#include "systemStatisticsWidget.h"
#include "ui_systemStatisticsWidget.h"SystemStatisticsWidget::SystemStatisticsWidget(QWidget *parent) :QWidget(parent),ui(new Ui::SystemStatisticsWidget),tagCpu(0),tagMemory(0)
{ui->setupUi(this);this->controlInit();
}SystemStatisticsWidget::~SystemStatisticsWidget()
{delete ui;
}void SystemStatisticsWidget::controlInit()
{this->ui->widgetPlot->yAxis->setTickLabels(false);connect(this->ui->widgetPlot->yAxis2, SIGNAL(rangeChanged(QCPRange)), this->ui->widgetPlot->yAxis, SLOT(setRange(QCPRange)));this->ui->widgetPlot->yAxis2->setVisible(true);this->ui->widgetPlot->axisRect()->addAxis(QCPAxis::atRight);this->ui->widgetPlot->axisRect()->axis(QCPAxis::atRight, 0)->setPadding(30);this->ui->widgetPlot->axisRect()->axis(QCPAxis::atRight, 1)->setPadding(30);graphCpu = this->ui->widgetPlot->addGraph(this->ui->widgetPlot->xAxis, this->ui->widgetPlot->axisRect()->axis(QCPAxis::atRight, 0));graphMemory = this->ui->widgetPlot->addGraph(this->ui->widgetPlot->xAxis, this->ui->widgetPlot->axisRect()->axis(QCPAxis::atRight, 1));graphCpu->setPen(QPen(QColor(250, 120, 0)));graphMemory->setPen(QPen(QColor(0, 180, 60)));this->graphCpu->setName(tr("CPU使用率"));this->graphMemory->setName(tr("内存使用率"));this->ui->widgetPlot->legend->setVisible(true);tagCpu = new AxisTag(graphCpu->valueAxis());tagCpu->setPen(graphCpu->pen());tagMemory = new AxisTag(graphMemory->valueAxis());tagMemory->setPen(graphMemory->pen());connect(this->ui->btnClearData,&QPushButton::clicked,this,&SystemStatisticsWidget::btnClickedSlot);connect(this->ui->btnScreenshotAndExport,&QPushButton::clicked,this,&SystemStatisticsWidget::btnClickedSlot);connect(this->ui->btnPause,&QPushButton::clicked,this,&SystemStatisticsWidget::btnClickedSlot);
}void SystemStatisticsWidget::setLabelText(double cpuUsage, double memoryUsage)
{
#define WARNING_VALUE 70
#define ERROR_VALUE 90if(cpuUsage > 90)this->ui->labelCpuUasge->setStyleSheet("color: rgb(255, 0, 0);font: 700 11pt \"Microsoft YaHei UI\";");else if(cpuUsage >= 70)this->ui->labelCpuUasge->setStyleSheet("color: rgb(255, 255, 0);font: 700 11pt \"Microsoft YaHei UI\";");elsethis->ui->labelCpuUasge->setStyleSheet("color: rgb(255, 255, 255);font: 700 11pt \"Microsoft YaHei UI\";");this->ui->labelCpuUasge->setText(QString::number(cpuUsage,'f',2));if(memoryUsage > 90){this->ui->labelMemoryUsage->setStyleSheet("color: rgb(255, 0, 0);font: 700 11pt \"Microsoft YaHei UI\";");}else if(memoryUsage >= 70){this->ui->labelMemoryUsage->setStyleSheet("color: rgb(255, 255, 0);font: 700 11pt \"Microsoft YaHei UI\";");}else{this->ui->labelMemoryUsage->setStyleSheet("color: rgb(255, 255, 255);font: 700 11pt \"Microsoft YaHei UI\";");}this->ui->labelMemoryUsage->setText(QString::number(cpuUsage,'f',2));
}void SystemStatisticsWidget::addData(double cpuUsage, double memoryUsage)
{if(this->isHidden())return;if(this->ui->btnPause->isChecked())return;graphCpu->addData(graphCpu->dataCount(), cpuUsage);graphMemory->addData(graphMemory->dataCount(), memoryUsage);this->ui->widgetPlot->xAxis->rescale();graphCpu->rescaleValueAxis(false, true);graphMemory->rescaleValueAxis(false, true);this->ui->widgetPlot->xAxis->setRange(this->ui->widgetPlot->xAxis->range().upper, 100, Qt::AlignRight);double graphCpuValue = graphCpu->dataMainValue(graphCpu->dataCount()-1);double graphMemoryValue = graphMemory->dataMainValue(graphMemory->dataCount()-1);tagCpu->updatePosition(graphCpuValue);tagMemory->updatePosition(graphMemoryValue);tagCpu->setText(QString::number(graphCpuValue, 'f', 2));tagMemory->setText(QString::number(graphMemoryValue, 'f', 2));this->ui->widgetPlot->replot();this->setLabelText(cpuUsage,memoryUsage);
}void SystemStatisticsWidget::popWindow(int x, int y, int width, int height)
{//实例阴影shadowQGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this->ui->frame);shadow->setOffset(0, 0);shadow->setColor(QColor(32, 101, 165));shadow->setBlurRadius(10);this->ui->frame->setGraphicsEffect(shadow);this->ui->frame->setStyleSheet("QFrame#frame{border:1px groove gray;""border-radius:10px;padding:5px;""background-color: rgb(255, 255, 255);}");this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);this->setAttribute(Qt::WA_TranslucentBackground, true);//计算显示位置
#define DIST_TO_MOUISE 10int screenWidth = QGuiApplication::screenAt(QCursor().pos())->geometry().width();int screenHeight = QGuiApplication::screenAt(QCursor().pos())->geometry().height();int showX,showY;if(x + width + DIST_TO_MOUISE > screenWidth)showX = x-width-DIST_TO_MOUISE;elseshowX = x + DIST_TO_MOUISE;if(y + height + DIST_TO_MOUISE > screenHeight)showY = y - height - DIST_TO_MOUISE;elseshowY = y + DIST_TO_MOUISE;this->setGeometry(showX,showY,width,height);this->show();
}void SystemStatisticsWidget::showEvent(QShowEvent *event)
{Q_UNUSED(event);this->graphCpu->data().data()->clear();this->graphMemory->data().data()->clear();
}void SystemStatisticsWidget::btnClickedSlot()
{QPushButton *btn = static_cast<QPushButton *>(sender());if( btn == this->ui->btnClearData){this->graphCpu->data().data()->clear();this->graphMemory->data().data()->clear();this->ui->widgetPlot->replot();}else if(btn == this->ui->btnScreenshotAndExport){
//        if(this->filePath.isEmpty())
//        {
//            this->filePath = QFileDialog::getSaveFileName(this, "Save document...", qApp->applicationDirPath(), "*.pdf");
//        }
//        if(this->filePath.isEmpty())
//            return;QScreen *screen = QGuiApplication::primaryScreen();int x = this->ui->widgetPlot->mapToGlobal(QPoint(0,0)).x();int y = this->ui->widgetPlot->mapToGlobal(QPoint(0,0)).y();QPixmap pixmapGrab = screen->grabWindow(0,x,y,this->ui->widgetPlot->width(),this->ui->widgetPlot->height());QString fileName = QDateTime::currentDateTime().toString("yyyy.MM.dd.hh.mm.ss")+".png";pixmapGrab.save(fileName);
//        // 打印和绘图对象
//        QPrinter printer;
//        QPainter painter;
//        printer.setOutputFormat(QPrinter::PdfFormat);
//        printer.setOutputFileName(this->filePath);
//        QMargins pageMargins(20, 20, 20, 20);
//        QPageLayout pageLayout;
//        pageLayout.setMode(QPageLayout::StandardMode);
//        pageLayout.setOrientation(QPageLayout::Portrait);
//        pageLayout.setPageSize(QPageSize(QPageSize::A4));
//        pageLayout.setUnits(QPageLayout::Millimeter);
//        pageLayout.setMargins(QMarginsF(pageMargins));
//        printer.setPageLayout(pageLayout);//        // QPrinter 和 QPainter关联
//        painter.begin(&printer);
//        painter.setFont(QFont("微软雅黑", 20));//        // 尺寸根据pdf的页面宽度缩放
//        if(pixmapGrab.width() > printer.width())
//        {
//            pixmapGrab = pixmapGrab.scaledToWidth(printer.width(), Qt::TransformationMode::SmoothTransformation);
//        }
//        // 生成新的一页并绘制上去
//        //printer.newPage();
//        painter.drawPixmap(0, 0, pixmapGrab.width(), pixmapGrab.height(), pixmapGrab);//        QString str = "\n"+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
//        QRect textRect(0,pixmapGrab.height(),printer.width(),20);
//        painter.drawText(textRect, Qt::AlignCenter, str);
//        // 关闭绘制
//        painter.end();}else if(btn == this->ui->btnPause){}
}

五、测试代码编写

1、首先在mainwindow.h中定义一个界面和定时器

    SystemStatisticsWidget *systemStatisticsWidget;QTimer mDataTimer;

在这里插入图片描述

2、在mainwindow.cpp中实例化和连接槽,并且定时添加数据

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow),systemStatisticsWidget(new SystemStatisticsWidget())
{ui->setupUi(this);connect(&mDataTimer, SIGNAL(timeout()), this, SLOT(timeroutSlot()));mDataTimer.start(40);this->ui->btnPopwindow->installEventFilter(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_btnShow_clicked()
{this->systemStatisticsWidget->show();
}void MainWindow::timeroutSlot()
{if(!systemStatisticsWidget->isHidden()){static uint64_t dataPoint = 0;dataPoint++;double cpu = qSin(dataPoint/50.0)+qSin(dataPoint/50.0/0.3843)*0.25;double memory = qCos(dataPoint/50.0)+qSin(dataPoint/50.0/0.4364)*0.15;this->systemStatisticsWidget->addData(cpu,memory);}
}bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{if(obj == this->ui->btnPopwindow){if(event->type() == QEvent::Enter){// auto evt = dynamic_cast<QEnterEvent *>(event);//  systemStatisticsWidget->popWindow(evt->globalPosition().x(),evt->globalPosition().y(),500,400);}else if(event->type() == QEvent::Leave){// systemStatisticsWidget->close();}}return QMainWindow::eventFilter(obj,event);
}

六、完整工程下载

点击链接下载
构建版本
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/70464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XREAL Air 2 Pro发布,加入电致变色技术,拓展AR眼镜使用场景

【2023年9月6日 中国北京】继刚刚宣布XREAL Air在全球销量突破20万台后&#xff0c;全球领先的消费级AR眼镜品牌XREAL今日于中国市场正式推出XREAL Air 2系列新品。全新Air 2系列包含两款AR眼镜产品&#xff1a;在显示、佩戴舒适性、音频等核心维度全面升级&#xff0c;体验全面…

Linux如何安装MySQL

Linux安装MySQL5.7 1、下载 官网下载地址&#xff1a;http://dev.mysql.com/downloads/mysql/ 2、复制下面几个文件 3、检查当前系统是否安装过mysql、检查当前mysql依赖环境、检查/tmp文件夹权限 1&#xff09;检查当前系统是否安装过mysql&#xff0c;执行安装命令前&am…

leetcode 20.有效括号 栈的简单应用

题目 数据结构 栈 code var isValid function(s) {// 空串和长度为奇数的字符串一定不符合要求if(!s || s.len%2){return true}let match {(: ),[: ],{: }}let stack []let len s.lengthfor(let i0; i<len; i){const ch s[i]if(ch[ || ch( || ch{){// 如果是左括号,…

London Dock丨伦敦一区的房产明星,拥揽泰晤士河美景,尽享都市奢华生活

生活在伦敦一区&#xff0c;似乎就意味跻身上流阶层 皆是精英环绕&#xff0c;也为下一代创造了极好的社区氛围 所谓“一方水土养一方人”&#xff0c;泰晤士河穿过的伦敦 也孕育着伦敦人的礼貌绅士与严谨认真。 河流&#xff0c;是城市发展的源头。 源远流长的塞纳河&…

【开发】视频集中存储/直播点播平台EasyDSS点播文件分类功能优化

视频推拉流EasyDSS视频直播点播平台&#xff0c;集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 TSINGSEE青犀视频的EasyDSS平台具有点播文件分类展示方法&#xf…

蓝桥杯备赛Day7——算法复杂度分析、前缀和思想

O(nlogn)算法可能达到的最优复杂度。快速排序算法是典型例子。 O(n^2)一个两重循环的算法,复杂度是O(n^2)。例如冒泡排序,是典型的两重循环。 O(n^3)、O(n^4)等等。 O(2n)一般对应集合问题。 例如一个集合中有n个数,要求输出它的所有子集。 O(n!)在集合问题中,如果要求按顺…

IP地址、子网掩码、网络地址、广播地址、IP网段

文章目录 IP地址IP地址分类子网掩码网络地址广播地址IP网段 本文主要讨论iPv4地址。 IP地址 实际的 IP 地址是一串32 比特的数字&#xff0c;按照 8 比特&#xff08;1 字节&#xff09;为一组分成 4 组&#xff0c;分别用十进制表示然后再用圆点隔开&#xff0c;这就是我们平…

Qt应用开发(基础篇)——复选按钮 QCheckBox 单选按钮 QRadioButton

一、前言 QCheckBox类与QRadioButton类继承于QAbstractButton&#xff0c;QCheckBox是一个带有文本标签的复选框&#xff0c;QRadioButton是一个带有文本标签的单选按钮。 按钮基类 QAbstractButton QCheckBox QCheckBox复选框是一个很常用的控件&#xff0c;拥有开关(选中和未…

远程访问群晖Drive并挂载为电脑磁盘同步备份文件「无需公网IP」

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

uni-app之android项目云打包

1&#xff0c;项目根目录&#xff0c;找到mainfest.json&#xff0c;如果appid是空的&#xff0c;需要生成一个appid 2&#xff0c;点击重新获取appid&#xff0c;这个时候需要登录&#xff0c;那就输入账号密码登录下 3&#xff0c;登陆后可以看到获取appid成功 4&#xff0c;…

【ES6】require、export和import的用法

在JavaScript中&#xff0c;require、export和import是Node.js的模块系统中的关键字&#xff0c;用于处理模块间的依赖关系。 1、require&#xff1a;这是Node.js中引入模块的方法。当你需要使用其他模块提供的功能时&#xff0c;可以使用require关键字来引入该模块。例如&…

恒运资本:股市板块轮动顺口溜?

股市是一个变化多端的场所&#xff0c;不同的板块会因为不同的方针、商场影响、经济形势等多种原因而有不同的体现。因而&#xff0c;不同时期不同板块的轮动也成为了研究的热门。下面咱们就通过一个顺口溜&#xff0c;来深化了解股市板块轮动&#xff1a; “钢铁、水泥、煤炭…

如何在Ubuntu 20.04|18.04上安装 FreeSwitch

如何在Ubuntu 20.04|18.04上安装FreeSwitch 什么是 FreeSwitch PBX&#xff1f;FreeSwitch PBX 系统有哪些功能&#xff1f;开始部署部署前准备开始安装freeswitch 安装完成错误及问题FAQ常见配置文件及说明修改默认端口&#xff1a;防火墙配置账号密码配置/添加新用户freeswit…

Nginx从安装到使用,反向代理,负载均衡

什么是Nginx&#xff1f; 文章目录 什么是Nginx&#xff1f;1、Nginx概述1.1、Nginx介绍1.2、Nginx下载和安装1.3、Nginx目录结构 2、Nginx命令2.1、查看版本2.2、检查配置文件正确性2.3、启动和停止2.4、重新加载配置文件2.5、环境变量的配置 3、Nginx配置文件结构4、Nginx具体…

【ES】笔记-Class类剖析

Class Class介绍与初体验ES5 通过构造函数实例化对象ES6 通过Class中的constructor实列化对象 Class 静态成员实例对象与函数对象的属性不相通实例对象与函数对象原型上的属性是相通的Class中对于static 标注的对象和方法不属于实列对象&#xff0c;属于类。 ES5构造函数继承Cl…

HTML emoji整理 表情符号

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>测试</title></head><body><div style"font-size: 50px;">&#128276</div><script>let count 0d…

Linux 系统服务日志查询 journalctl:查询 systemd 日记

journalctl&#xff1a;查询 systemd 日记 systemd 在取代 SUSE Linux Enterprise 12 中的传统 init 脚本时&#xff08;参见第 13 章 “systemd 守护程序”&#xff09;&#xff0c;引入了自身的称为日记的日志记录系统。由于所有系统事件都将写入到日记中&#xff0c;因此&a…

3.运行项目

克隆项目 使用安装的git克隆vue2版本的若依项目&#xff0c;博主使用的版本是3.8.6. git clone https://gitee.com/y_project/RuoYi-Vue.git目录结构如下图所示&#xff0c;其中ruoyi-ui是前端的内容&#xff0c;其它均为后端的内容。 配置mysql数据库 在数据库里新建一个…

【ARM CoreLink 系列 1 -- CoreLink 系列 产品介绍】

文章目录 ARM CoreLink 介绍ARM CoreLink InterconnectARM CoreLink 处理器外设ARM CoreLink Memory Controllers ARM CoreLink 介绍 ARM的CoreLink系列产品是一套能够进行高效互联的组件和工具&#xff0c;它们用于构建高性能、低功耗的嵌入式和消费电子设备。CoreLink产品系…

vue3组件通信学习笔记

1、Prop 父组件 <template><div class"parent"><h1>我是父元素</h1><Child :msg"msg"></Child></div> </template><script setup> import Child from ./Child.vue let msg ref(我是父组件的数据…