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.rhkb.cn/news/124589.html

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

相关文章

2023年高教社杯数学建模国赛 赛题浅析

2023年国赛如期而至&#xff0c;为了方便大家尽快确定选题&#xff0c;这里将对赛题进行浅析&#xff0c;以分析赛题的主要难点、出题思路以及选择之后可能遇到的难点进行说明&#xff0c;方便大家尽快确定选题。 难度排序 B>A>C 选题人数 C>A>B (预估结果&…

matlab 计算点云中值

目录 一、概述1、算法概述2、主要函数二、代码示例三、结果展示四、参数解析输入参数输出参数五、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、概述

网络编程套接字 | UDP套接字

前面的文章中我们叙述了网络编程套接字的一些预备知识点&#xff0c;从本文开始我们就将开始UDP套接字的编写。本文中的服务端与客户端都是在阿里云的云服务器进行编写与测试的。 udp_v1 在v1的版本中我们先来使用一下前面讲过得一些接口&#xff0c;简单的构建一个udp服务器…

HarmonyOS/OpenHarmony(Stage模型)应用开发组合手势(一)连续识别

组合手势由多种单一手势组合而成&#xff0c;通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型&#xff0c;支持连续识别、并行识别和互斥识别三种类型。 .GestureGroup(mode:GestureMode, …gesture:GestureType[]) mode&#xff1a;必选参数&#xff0c;为G…

MP中的字段还可以利用函数来查询拼接sql

//根据value查询GetMapping("getTest")public List<HashMap> getTest() {QueryWrapper<TTest> queryWrapper new QueryWrapper<>();queryWrapper.eq("substr(name,1,2)","99999");List<TTest> list1 testService.list…

【网络通信 -- WebRTC】Open WebRTC Toolkit 环境搭建指南

【网络通信 -- WebRTC】Open WebRTC Toolkit -- OWT-Server 编译安装指南 【1】OWT Server 与 Web Demo 视频会议环境搭建 【1.1】编译 OWT Server 安装依赖 ./scripts/installDepsUnattended.sh编译 scripts/build.js -t all --check 注意若不支持硬件加速则采用如下命令 s…

[CISCN 2019华北Day1]Web1

文章目录 涉及知识点解题过程 涉及知识点 phar反序列化文件读取 解题过程 打开题目&#xff0c;注册用户为admin 进去发现有文件上传的功能&#xff0c;我们随便上传个图片 然后就有下载和删除两个功能 我们尝试抓包下载文件的功能 发现参数可控&#xff0c;我们尝试读取一下…

Navicat15工具连接PostgreSQL15失败

1.错误现象及原因 错误现象&#xff1a; 错误原因&#xff1a; postgresql 15版本中 pg_database 系统表把 datlastsysoid 列删除了&#xff0c;所以造成了此错误。 2.解决方法 &#xff08;1&#xff09;将Navicat工具更新到官网最新版本。 &#xff08;2&#xff09;更换…

划片机实现装片、对准、切割、清洗到卸片的自动化操作

划片机是一种用于切割和分离材料的设备&#xff0c;通常用于光学和医疗、IC、QFN、DFN、半导体集成电路、GPP/LED氮化镓等芯片分立器件、LED封装、光通讯器件、声表器件、MEMS等行业。划片机可以实现从装片、对准、切割、清洗到卸片的自动化操作。 以下是划片机实现这些操作的步…

回复:c#的Winform如何让ComboBox不显示下拉框?https://bbs.csdn.net/topics/392565412

组合框.Parent this;组合框.Items.AddRange(new object[] { "111", "222", "333", "444" });组合框.DropDownHeight 1;组合框.SelectedIndex 0;//组合框.DropDownStyle ComboBoxStyle.Simple; ComboBox 组合框 new ComboBox();Li…

Web framework-Gin(二)

目录 一、Gin 1、Ajax 2、文件上传 2.1、form表单中文件上传(单个文件) 2.2、form表单中文件上传(多个文件) 2.3、ajax上传单个文件 2.4、ajax上传多个文件 3、模板语法 4、数据绑定 5、路由组 6、中间件 一、Gin 1、Ajax AJAX 即“Asynchronous Javascript And XM…

web端调用本地摄像头麦克风+WebRTC腾讯云,实现直播功能

目录 关于直播直播流程直播视频格式封装推流和拉流 获取摄像头和麦克风权限navigator.getUserMedia()MediaDevices.getUserMedia() WebRTC腾讯云快直播 关于直播 视频直播技术大全、直播架构、技术原理和实现思路方案整理 直播流程 视频采集端&#xff1a; 1、视频采集&#…

简述视频智能分析EasyCVR视频汇聚平台如何通过“AI+视频融合”技术规避八大特殊作业风险

视频智能分析EasyCVR视频汇聚平台可以根据不同的场景需求&#xff0c;让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上&#xff0c;视频云存储平台EasyCVR可实现视频实时直播、云端录像、视频云存储、视频存储磁盘阵列、录…

uniapp 实现滑动元素删除效果

官网地址&#xff1a;uni-app官网 (dcloud.net.cn) 最终效果如下图&#xff1a; 滑动删除需要用到 uni-ui 的 uni-swipe-action 组件和 uni-swipe-action-item 属性名类型可选值默认值是否必填说明left-optionsArray/Object--否左侧选项内容及样式right-optionsArray/Object--…

Vue2+Vue3基础入门到实战项目(七)——智慧商城项目

Vue 核心技术与实战 智慧商城 接口文档&#xff1a;https://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080 演示地址&#xff1a;http://cba.itlike.com/public/mweb/#/ 01. 项目功能演示 1.明确功能模块 启动准备好的代码&#xff0c;演示…

【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

【PHP代码审计】反序列化漏洞实战

文章目录 概述资源下载地址Typecho代码审计-漏洞原理call_user_func()_applyFilter()、get()与__get__toString()__construct()install.php POC利用漏洞利用复现利用链执行phpinfo()GET利用POST利用 getshell生成payload漏洞利用蚁剑连接 总结 概述 序列化&#xff0c;“将对象…

从Matrix-ResourceCanary看内存快照生成-ForkAnalyseProcessor(1)

前文看到AutoDumpProcessor的处理逻辑主要是生成&#xff0c;裁剪hprof文件并回调到PluginListener中&#xff0c;接下来我们来看下ForkAnalyseProcessor的处理逻辑。 ForkAnalyseProcessor public class ForkAnalyseProcessor extends BaseLeakProcessor {private static fi…

Nginx 本地部署服务

nginx 部署服务 一、下载二、解压三、文件替换四、浏览器中输入五、离线部署瓦片服务 一、下载 可以到官网下载&#xff0c;官方网址&#xff1a;https://nginx.org/也可以用我发的包 二、解压 三、文件替换 解压打开后文件&#xff0c;双击 nginx.exe 浏览器输入 localhost…

对极几何与三角化求3D空间坐标

一&#xff0c;使用对极几何约束求R,T 第一步&#xff1a;特征匹配。提取出有效的匹配点 void find_feature_matches(const Mat &img_1, const Mat &img_2,std::vector<KeyPoint> &keypoints_1,std::vector<KeyPoint> &keypoints_2,std::vector&l…