QT案例-通过QCustomPlot库绘制Window系统CPU温度实时折线图

之前项目中涉及到了获取硬件信息内容,对CPU的温度监控有点兴趣,观察和百度发现鲁大师和驱动人生的CPU温度监控貌似是用驱动实现的,有点太高大上了,搞不懂。后面经过到处查找资料终于找到了Qt在Windows 环境下监控CPU等硬件温度/运行速度等信息的解决方法。
这一篇注意介绍QCustomPlot库绘制每两秒获取的CPU温度数据:
根据获取的Window系统的CPU温度数据,使用QCustomPlot库绘制温度折线图,包括实现x轴时间线,折现背景渐变绘图,获取温度值,每两秒实时显示温度,等涉及的QCustomPlot库的使用。

目录导读

    • QCustomPlot库简要介绍(文言一心)
    • 功能描述
    • 绘制样式一
      • QCustomPlot 控件样式具体实现
        • 添加 表格边框线、启用图例等默认配置
        • 设置 X轴显示时间
        • 添加 竖线分割线和显示内容文字框
        • 设置 从折线向下的一个渐变背景
        • 初始化绘图 QCPGraph类
        • 绑定数据
    • 绘制样式二
      • 在上面 QCustomPlot 控件样式的基础上进行修改
        • 修改 初始化绘图 QCPGraph类
        • 绑定数据

QCustomPlot库简要介绍(文言一心)

QCustomPlot是一个功能强大、易于使用的Qt C++图形库,它提供了丰富的API和强大的功能,非常适合用于创建各种2D图形和进行数据可视化。无论是静态图形还是实时数据可视化,
QCustomPlot都能提供出色的性能和效果。
基本概述:

  • 功能定位QCustomPlot是一个用于创建静态或实时2D图形的C++类库,构建在Qt应用框架之上,提供了一套丰富的API用于创建各种常见的2D图形,包括散点图、曲线图、条形图、饼图、直方图等。
  • 特点QCustomPlot没有进一步的依赖关系,并且有据可查。它专注于制作美观、出版质量的2D绘图、图形和图表,以及为实时可视化应用程序提供高性能服务。
  • 兼容性QCustomPlot建立了高达Qt 6.0的兼容性(保持兼容性一直到4.6),并包括许多功能添加、错误修复和较小的改进。它需要C++11支持。

主要特性:
1. 支持多种图形类型: QCustomPlot支持各种类型的2D图形,如线图、散点图、条形图、饼图、直方图等。
2. 数据可视化: 支持多种数据可视化形式,如颜色映射、水平线、垂直线等。
3. 自定义轴: 用户可以在QCustomPlot中自定义轴的范围、标签、刻度线等。
4. 高亮显示和注释: 可以高亮显示图形中的特定部分,并添加注释。
5. 交互性: 支持图形的缩放、平移、选择和鼠标悬停等交互操作。
6. 实时更新: 可以实时更新图形,非常适合展示动态数据。
7. 输出功能: 用户可以将QCustomPlot中的图形保存为各种格式的图像文件(如PDF、PNG、JPG、BMP等),或直接打印出来。
8. 图层控制: 支持多图层绘制,用户可以控制各个图层的顺序和可见性。
9. 自定义图例: 可以自动为用户创建的图形创建图例,用户也可以完全控制图例的样式和位置。

使用参考:
QCustomPlot绘图类详解(大白话)
QCustomPlot 官网

示例是Window系统环境, 使用 Qt Creator 5.13.1 和Mscv2022编译器使用QCustomPlot 库绘制折线图,
只需要引用qcustomplot.hqcustomplot.cpp文件,
以及在Pro文件中添加QT += printsupport 就能直接绘制。

功能描述

根据第三方库每两秒获取的Window系统的CPU温度数据 ,使用QCustomPlot 库绘制温度折线图。

绘制样式一

参考官方interaction示例完成以下样式:
在这里插入图片描述

QCustomPlot 控件样式具体实现

  • 添加 表格边框线、启用图例等默认配置
//! 表格边框线
customPlot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
customPlot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
customPlot->xAxis->grid()->setSubGridVisible(true);
customPlot->yAxis->grid()->setSubGridVisible(true);

//! 设置 坐标轴是否可选,图例是否可选 实例是否可选
customPlot->setInteractions( QCP::iSelectLegend | QCP::iSelectPlottables);

//! 设置一个默认范围
customPlot->xAxis->setRange(QDateTime::currentSecsSinceEpoch()-120, QDateTime::currentSecsSinceEpoch());
customPlot->yAxis->setRange(0, 100);

//! 完全填充
customPlot->axisRect()->setupFullAxesBox();

customPlot->xAxis->setLabel("时间(S)");
customPlot->yAxis->setLabel("温度(℃)");

//! 启用图例
customPlot->legend->setVisible(true);
//    QFont legendFont = font();
//    legendFont.setPointSize(10);
//    ui->customPlot->legend->setFont(legendFont);
//    ui->customPlot->legend->setSelectedFont(legendFont);
customPlot->legend->setSelectableParts(QCPLegend::spItems); // legend box shall not be selectable, only legend items
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop|Qt::AlignLeft);

//! 设置一个绘图标题
customPlot->plotLayout()->insertRow(0);
QCPTextElement *title = new QCPTextElement(customPlot, "CPU Temperature", QFont("sans", 17, QFont::Bold));
customPlot->plotLayout()->addElement(0, 0, title);

  • 设置 X轴显示时间

设置X轴为时间轴,此时X轴数据对应值为 [QDateTime::currentSecsSinceEpoch()]

 QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);
  dateTicker->setDateTimeSpec(Qt::LocalTime); // 设置日期和时间规范为协调世界时(UTC)
  dateTicker->setTickCount(5); // 设置刻度数量
  dateTicker->setDateTimeFormat("yyyy-MM-dd \n hh:mm:ss");
  customPlot->xAxis->setTicker(dateTicker);

值得注意的是:使用毫秒时间戳[QDateTime::currentMSecsSinceEpoch()]时,X轴转换成时间会混乱,而使用秒[QDateTime::currentSecsSinceEpoch()]X轴时间正常
但是参考:qcustomplot使用&x轴显示时间 毫秒值是正常的,不知道是不是Qt版本的问题。

  • 添加 竖线分割线和显示内容文字框

QCustomPlot绘图中添加一条根据鼠标移动移动的竖线(QCPItemLine);
和添加一个点击显示内容的文字框(QCPItemText) 同时绑定到竖线的左侧显示:

	//! 初始化 一个分割线 用于定位鼠标位置
   QPointer<QCPItemLine> Service_Line=new QCPItemLine(customPlot);
    // 设置线的起点为 (5, 0)(注意这里的0可能是Y轴的最小值,也可能是其他值,取决于你的需求)
    Service_Line->start->setType(QCPItemPosition::ptPlotCoords);
    qint64 Line_x=QDateTime::currentSecsSinceEpoch()+5;
    Service_Line->start->setCoords(Line_x, 0); // X=5, Y轴最小值处
    // 设置线的终点为 (5, 1)(这里的1表示Y轴的最大值,使用轴的比例坐标)
    Service_Line->end->setType(QCPItemPosition::ptPlotCoords);
    Service_Line->end->setCoords(Line_x, 100); // X=5, Y轴最大值处

    // 设置线的颜色和线宽等属性(可选)
    Service_Line->setPen(GetCPItemLinePen(customPlot->size())); // 红色,线宽为2
    Service_Line->setVisible(true);

    //!初始化 一个文本框
    QPointer<QCPItemText> Service_Text= new QCPItemText(customPlot);//在QCustomplot中新建文字框
    Service_Text->setPositionAlignment(Qt::AlignRight|Qt::AlignTop);//文字布局:顶、左对齐
    Service_Text->position->setType(QCPItemPosition::ptAxisRectRatio);//位置类型(当前轴范围的比例为单位/实际坐标为单位)
    Service_Text->position->setCoords(0.4, 0.05); //把文字框放在X轴的中间,Y轴的最顶部
    Service_Text->setText("Text Item Demo");
    Service_Text->setPen(QPen(Qt::white)); //字体颜色
    Service_Text->setPadding(QMargins(2,2,2,2));
    Service_Text->position->setParentAnchorX(Service_Line->anchor("start"));
    Service_Text->setColor(Qt::white);
    Service_Text->setBrush(QColor("#383F5B"));
    Service_Text->setVisible(false);

参考:QCustomPlot系列(6)-在图中插入文本框/直线箭头/图片/矩形/椭圆/游标等

  • 使用QLinearGradient 实现渐进效果:
    给(QCPItemLine)竖线添加一个从上到下,从白色到黑色在到白色的渐进效果画笔;
QPen InitPlotDefaultStyle::GetCPItemLinePen(QSize size)
{
    //! 设置渐进
    //! 因为 QLinearGradient 需要设置高度大小 所以需要动态修改,参考:
    //! QGradient(渐变填充): https://blog.csdn.net/qq_45303986/article/details/127934344
    //!
    QLinearGradient gradient(0, 15, 0, size.height()-25); // 从 (0,0) 到 (100,100) 的渐变
    gradient.setColorAt(0, QColor(255, 255, 255, 0));
    gradient.setColorAt(0.5, Qt::black);
    gradient.setColorAt(1, QColor(255, 255, 255, 0));
    // 创建一个 QBrush 并设置渐变
    QBrush brush(gradient);

    QPen Pen;
    Pen.setColor(Qt::black);
    Pen.setWidth(3);
    Pen.setBrush(brush);
    return Pen;
}

注意:
在使用QLinearGradient 实现渐变效果时,需要设置QCustomPlot控件的高度,这意味着需要在QCustomPlot控件大小发生变化时,刷新画笔;
需要在QCustomPlot 控件的resizeEvent事件中添加一个resizeChange信号

/*! \internal
  
  Event handler for a resize of the QCustomPlot widget. The viewport (which becomes the outer rect
  of mPlotLayout) is resized appropriately. Finally a \ref replot is performed.
*/
void QCustomPlot::resizeEvent(QResizeEvent *event)
{
  Q_UNUSED(event)
  // resize and repaint the buffer:
  setViewport(rect());
  replot(rpQueuedRefresh); // queued refresh is important here, to prevent painting issues in some contexts (e.g. MDI subwindow)

  // update add 
  emit resizeChange(event->size());
}

然后绑定信号实时修改绘制的画笔:


//! 控件大小改变
//connect(customPlot,&QCustomPlot::resizeChange,this,&InitPlotDefaultStyle::Slots_resizeChange);
void InitPlotDefaultStyle::Slots_resizeChange(QSize size)
{
	if(!Service_Line.isNull())
	    Service_Line->setPen(GetCPItemLinePen(size));

	//! 折线图下面的渐变
	for(int i=0;i<graphs.count();i++)
	{
	    graphs[i]->setBrush(GetGraphsBrush(customPlot->size(),colorPen[i]));
	}
}
    
  • 设置 从折线向下的一个渐变背景

同样使用QLinearGradient 实现折线到白色透明的一个渐变,同时在大小改变 resizeChange信号时刷新画笔刷子;

QBrush InitPlotDefaultStyle::GetGraphsBrush(QSize size,QColor color)
{
    //! 创建渐进效果
    QLinearGradient gradient(0, 10, 0, size.height()-20); // 从 (0,0) 到 (100,100) 的渐变
    gradient.setColorAt(0, color); // 起点颜色为红色
    gradient.setColorAt(1, QColor(255, 255, 255, 0)); // 终点颜色为透明
    //! 创建一个 QBrush 并设置渐变
    QBrush brush(gradient);
    return brush;
}
  • 初始化绘图 QCPGraph类

初始化每个CPU核心对应的QCPGraph绘图,并随机颜色,设置绘图图层和渐变效果。

void InitPlotDefaultStyle::InitGrap(QStringList keys)
{
    KeysV.clear();
    //! 记录每条折线图对映画笔颜色,用于渐变
    colorPen.clear();
    //! 保存每个折线的 QCPGraph*
    graphs.clear();

    //! 图例名称
    KeysV.append(keys);
    for(int i=0;i<KeysV.count();i++)
    {
        QCPGraph *graph1 = customPlot->addGraph();

        //! 随机颜色
        QColor pencolor=QColor(std::rand()%245+10, std::rand()%245+10, std::rand()%245+10);
        colorPen.append(pencolor);

        //! 设置画笔
        QPen graphPen;
        graphPen.setColor(pencolor);
        graphPen.setWidthF(2);
        graph1->setPen(graphPen);
        //!  圆点
        graph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 2));
        //! 随机点样式
//        if (std::rand()%100 > 50)
//        graph1->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)(std::rand()%14+1),5));

        //! 设置渐进绘图 从线向下绘图
        graph1->setBrush(GetGraphsBrush(customPlot->size(),pencolor));
        graph1->setName(KeysV[i]);
        graph1->setLineStyle((QCPGraph::lsLine));

        //! 设置所在图层
        customPlot->addLayer(QString(KeysV[i]).toStdString().c_str(), customPlot->layer("main"), QCustomPlot::limAbove);
        graph1->setLayer(QString(KeysV[i]).toStdString().c_str());

        graphs.append(graph1);
    }
    customPlot->replot();

}
  • 绑定数据

绑定每两秒监测线程传来的数据,

void InitPlotDefaultStyle::AddDataToCpuKeyValue(qint64 row,QList<double> Data)
{
    customPlot->xAxis->setRange(row,120, Qt::AlignRight);
    for (int i = 0; (i < Data.count() && i < customPlot->graphCount()); ++i) {
        customPlot->graph(i)->addData(row, Data[i]);
    }
    customPlot->replot();
}

值得注意的是设置X轴的 setRange 使最新的内容始终显示在最右边,
120为整个x轴显示间隔120秒内的数据:
customPlot->xAxis->setRange(row,120, Qt::AlignRight);
rowQDateTime::currentSecsSinceEpoch() 数据。

绘制样式二

参考官方的axis-tags示例完成以下样式,显示CPU最新温度:
在这里插入图片描述

在上面 QCustomPlot 控件样式的基础上进行修改

  • 修改 初始化绘图 QCPGraph类
void InitPlotDetailStyle::InitGrap(QStringList keys)
{

    KeysV.clear();
    colorPen.clear();
    graphs.clear();
    KeysV.append(keys);
    for(int i=0;i<KeysV.count();i++)
    {
//        customPlot->axisRect()->axis(QCPAxis::atRight, i)->setPadding(30);
        QCPGraph *graph1 = customPlot->addGraph();

        //! 随机颜色
        QColor pencolor=QColor(std::rand()%245+10, std::rand()%245+10, std::rand()%245+10);
        colorPen.append(pencolor);

        //! 设置画笔
        QPen graphPen;
        graphPen.setColor(pencolor);
        graphPen.setWidthF(2);
        graph1->setPen(graphPen);

        QCPAxis * tagAxis= customPlot->axisRect()->addAxis(QCPAxis::atRight);
        tagAxis->setRange(0,100);
        tagAxis->setTickLabels(false);
        tagAxis->setPadding(55);
        // create tags with newly introduced AxisTag class (see axistag.h/.cpp):
        AxisTag* mTag1 = new AxisTag(tagAxis);
        mTag1->setPen(graphPen);
        //! QList<QPointer<AxisTag>>
        graphs_AxisTag.append(mTag1);

        //!  圆点
        graph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 2));
        //! 随机点样式
//        if (std::rand()%100 > 50)
//        graph1->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)(std::rand()%14+1),5));

        //! 设置渐进绘图 从线向下绘图
        graph1->setBrush(GetGraphsBrush(customPlot->size(),pencolor));
        graph1->setName(KeysV[i]);
        graph1->setLineStyle((QCPGraph::lsLine));

        //! 设置所在图层
        customPlot->addLayer(QString(KeysV[i]).toStdString().c_str(), customPlot->layer("main"), QCustomPlot::limAbove);
        graph1->setLayer(QString(KeysV[i]).toStdString().c_str());

        graphs.append(graph1);
    }
    customPlot->replot();

}

AxisTag 类是官方示例中的 "axistag.h"文件中的类,
与上面初始化
QCPGraph
类 不同的是
每添加一条折线图就需要在右边添加一个Y轴,并赋值给AxisTag类:
customPlot->axisRect()->addAxis(QCPAxis::atRight)

  • 绑定数据

修改绑定数据的同时,修改 AxisTag类的值;

void InitPlotDetailStyle::AddDataToCpuKeyValue(qint64 row,QList<double> Data)
{
    customPlot->xAxis->setRange(row,120, Qt::AlignRight);
    for (int i = 0; (i < Data.count() && i < customPlot->graphCount()); ++i) {
        customPlot->graph(i)->addData(row, Data[i]);

        graphs_AxisTag[i]->updatePosition(Data[i]);
        graphs_AxisTag[i]->setText(QString::number(Data[i], 'f', 2));
    }
    customPlot->replot();

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

android文本长按复制

android文本长按复制 &#x1f4d6;1. 长按直接复制✅步骤一&#xff1a;定义一个TextView✅步骤二&#xff1a;为TextView注册长按事件✅步骤三&#xff1a;弹出系统复制功能 &#x1f4d6;2. 长按弹框确认复制✅步骤一&#xff1a;定义一个TextView✅步骤二&#xff1a;封装P…

vue详解

目录 ​编辑 常用指令 v-for v-bind v-if & v-show v-if v-show v-on v-model Vue生命周期 ​编辑 Axios Axios使用步骤 Axios-请求方式别名 Vue简单案例 常用指令 指令:HTML标签上带有 v-前缀的特殊属性&#xff0c;不同的指令具有不同的含义&#xff0c;可…

2.5 C#视觉程序开发实例1----CamManager实现模拟相机采集图片(Form_Vision部分代码)

2.5 C#视觉程序开发实例1----CamManager实现模拟相机采集图片(Form_Vision部分代码) 1 目标效果视频 CamManager 2 增加一个class IMG_BUFFER 用来管理采集的图片 // <summary> /// IMG_BUFFER 用来管理内存图片的抓取队列 /// </summary> public class IMG_BUFF…

imx6ull/linux应用编程学习(14) MQTT基础知识

什么是mqtt&#xff1f; 与HTTP 协议一样&#xff0c; MQTT 协议也是应用层协议&#xff0c;工作在 TCP/IP 四层模型中的最上层&#xff08;应用层&#xff09;&#xff0c;构建于 TCP/IP协议上。 MQTT 最大优点在于&#xff0c;可以以极少的代码和有限的带宽&#xff0c;为连接…

electron在VSCode和IDEA及webStrom等编辑器控制台打印日志乱码

window10环境下设置 1.打开Windows设置 2.打开时间和语言&#xff0c;选择语言菜单、如何点击管理语言设置 3.打开之后选择管理&#xff0c;选择更改系统区域设置&#xff0c;把Beta版&#xff1a;使用Unicode UTF-8提供全球语言支持 勾上&#xff0c;点击确定&#xff0c;…

后端学习(一)

添加数据库包&#xff1a; 数据库连接时 发生错误&#xff1a; 解决方式&#xff1a; SqlConnection conn new SqlConnection("serverlocalhost;databaseMyBBSDb;uidsa;pwd123456;Encryptfalse;") ;conn.Open();SqlCommand cmd new SqlCommand("SELECT * FROM…

Debug-017-elementUI-el-cascader组件首次选择选项不触发表单的自定义校验

前情提要&#xff1a; 今天维护一个表单校验的时候发现一件事情&#xff0c;就是在表单中使用了 el-cascader组件&#xff0c;希望根据接口返回数据去动态校验一下这里面的选项&#xff0c;符合逻辑就通过自定义的表单校验&#xff0c;不符合就在这一项的下面标红提示。做的时候…

OpenHarmony 入门——单元测试UnitTest快速入门

引言 OpenHarmony 的单元测试&#xff08;UnitTest&#xff09;是一个关键的软件开发过程&#xff0c;它确保代码的各个部分能够按预期工作&#xff0c;OpenHarmony的测试框架中提供了很多种的单元测试&#xff0c;今天简单介绍下UnitTest 类型的TDD测试。 OpenHarmony 的TDD …

群体优化算法---文化算法介绍,求解背包问题

介绍 文化算法&#xff08;Cultural Algorithm, CA&#xff09;是一种基于文化进化理论的优化算法&#xff0c;首次由Robert G. Reynolds在20世纪90年代提出。文化算法通过模拟人类社会中的文化进化过程&#xff0c;利用个体与群体的双重进化机制来解决优化问题。其基本思想是…

MGRE复习综合实验

R1与R5之间使用ppp的pap认证&#xff0c;R5为主认证方&#xff1a; R1 interface Serial4/0/0ip address 15.0.0.1 8link-protocol pppppp pap local-user huawei password cipher 123456 R5 aaalocal-user huawei password cipher 123456local-user huawei service-type…

海外媒体发稿-全媒体百科

全球知名媒体机构 在全球范围内&#xff0c;有许多知名的新闻机构负责报道世界各地的新闻事件。以下是一些国外常见的媒体机构&#xff1a; AP&#xff08;美联社&#xff09;合众国际社&#xff08;UPI&#xff09;AFP(法新社)EFE&#xff08;埃菲通讯社&#xff09;Europa …

JavaSE学习笔记第二弹——对象和多态(上)

目录 面向对象基础 面向对象程序设计的定义 类的基本结构 成员变量 成员方法 方法定义与使用 设计练习 方法重载 构造方法 静态变量和静态方法 String和StringBuilder 基本含义 区别 总结 今天我们继续来学习JavaSE&#xff0c;扩展和Java相关的知识&#xff0c;…

【软件分享】气象绘图软件Panoply

气象是大气中的物理现象&#xff0c;气象要素则是表明大气物理状况的要素&#xff0c;主要的气象要素有降水、风、气压、湿度等。为了研究气象要素在空间上的分布和运动状况&#xff0c;我们需要对气象要素进行空间上进行可视化&#xff0c;这个时候就需要气象领域的一些的绘图…

FastReport 指定sql,修改数据源 ( 非DataSet修改 )

FastReport 指定sql&#xff0c;修改数据源&#xff0c;非DataSet修改 介绍报告文件&#xff1a; codetest.frx 文件核心代码&#xff1a;&#xff08;扩展&#xff09;小结一下&#xff1a; 介绍 在FastReport中&#xff0c;经常会遇到需要给 sql 加条件的情况。 &#xff0…

Open3D KDtree的建立与使用

目录 一、概述 1.1kd树原理 1.2kd树搜索原理 1.3kd树构建示例 二、常见的领域搜索方式 2.1K近邻搜索&#xff08;K-Nearest Neighbors, KNN Search&#xff09; 2.2半径搜索&#xff08;Radius Search&#xff09; 2.3混合搜索&#xff08;Hybrid Search&#xff09; …

进程 VS 线程(javaEE篇)

&#x1f341; 个人主页&#xff1a;爱编程的Tom&#x1f4ab; 本篇博文收录专栏&#xff1a;JavaEE初阶&#x1f449; 目前其它专栏&#xff1a;c系列小游戏 c语言系列--万物的开始_ 等 &#x1f389; 欢迎 &#x1f44d;点赞✍评论⭐收藏&#x1f496;三连支…

shell脚本编程的练习

字符测试方法&#xff1a; 双目测试 比较两个字符串&#xff1a; &#xff1a;等于,等值比较 &#xff01;&#xff1a;不等 单目测试&#xff1a; -n $stringVar:字符串是否为空&#xff0c;不空为真&#xff0c;空则为假 -z $stringVar:字符串是否为空&#xff0c;空则为…

xxl-job集成SpringBoot

安装xxl-job客户端一般有很多方式&#xff0c;我这里给大家提供两种安装方式&#xff0c;包含里面的各项配置等等。 前期需要准备好MySQL数据库。复制SQL到数据库里面。 # # XXL-JOB v2.4.2-SNAPSHOT # Copyright (c) 2015-present, xuxueli.CREATE database if NOT EXISTS x…

终于找到了免费的C盘清理软件(极智C盘清理)

搜了很久&#xff0c;终于让我找到了一款 完全免费的C盘清理软件&#xff08;极智C盘清理&#xff09;。 点击前往官网免费使用极智C盘清理软件&#xff1a; C盘清理 用户好评 完全免费的极智C盘清理 用极智C盘清理清理了下系统的临时文件、缓存等无用数据文件&#xff0c;C盘终…

JavaDS —— 顺序表ArrayList

顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。在数组上完成数据的增删查改。在物理和逻辑上都是连续的。 模拟实现 下面是我们要自己模拟实现的方法&#xff1a; 首先我们要创建一个顺序表&#xff0c;顺序表…