前面我们读取了CPU的信息,并且以QLabel的形式显示了出来,但是只是一些文字的显示,所以这次我想对这些信息做一下美化,让他们看起来好看一些。
首先,我们参考一下Windows是怎么做的。
这是Windows下任务管理器中的信息,以波形图的方式展现了出来,那么我就仿造他做一个吧
我要显示4个信息的波形图,CPU使用率,CPU温度,内存信息,硬盘信息,所以要创建四个Widget窗口,并且画波形图的方法都是一样的,只是传入的值不一样,所以我子类化了一个QWidget,命名为QGraph,在ui设计界面,将控件的类提升为自定义的QGraph类
首先,头文件中的构造函数
#define ROWS 5 //5行
#define COLS 20 //20列
class QGraph : public QWidget
{
Q_OBJECT
public:
explicit QGraph(QWidget *parent = 0);
~QGraph();
QColor background_color, line_color; //保存背景色和前景色
int graph_heigh,graph_width; //行间距和列间距
int startX,startY; //起始的坐标
void setColor(QColor bgcolor, QColor lcolor); //设置背景色和前景色,上级调用
void setRate(double rate); //设置数据,上级调用
void dataReset(); //清空数据,上级调用
protected:
void paintEvent(QPaintEvent *); //画图事件
private:
int cur; //最近一次更新数据的数组索引值
int length = COLS*2+2; //数组长度
double RateData[COLS*2+2]; //用于保存数据,只保存最近的42个数据
};
观察Windows的界面发现,背景的栅栏使用很浅的颜色画的,线条用深色的颜色,而用于填充的颜色介于背景色与前景色之间。在主窗口实例化了4个窗口,分别为
ui->cpu_info_widget
ui->cpu_temp_widget
ui->mem_info_widget
ui->disk_info_widget
所以我们在主窗口为每个对象都传入各自的背景色和前景色
ui->cpu_info_widget->setColor(QColor(QRgb(0xd9f4fc)), QColor(QRgb(0x12bff3))); //浅蓝色
ui->cpu_temp_widget->setColor(QColor(QRgb(0xfeb9bb)), QColor(QRgb(0xe53439))); //红色
ui->mem_info_widget->setColor(QColor(QRgb(0xeed8f9)), QColor(QRgb(0x9e2ed6))); //紫色
ui->disk_info_widget->setColor(QColor(QRgb(0xeaf9e2)), QColor(QRgb(0x65c133))); //绿色
我们每次打开界面的时候,要从界面的最右端开始画图,所以设置了一个清零的方法,每次显示时调用一次。
最重要的就是数据的保存和画图的过程了。
首先我说一下数据的保存。因为我们有20列,所以我初始化了40+2个数组,最后增加的2个是为了在数组循环的时候不重复。一开始,将数组全部赋值为1,每传入一个值就往数组中写入,然后cur标志位+1,当然这里要用length进行模除,是为了当cur超过length的长度时,又可以从0开始计数,达到了循环数组的目的,也就是超过40后的数据会覆盖最远一次记录的数据。
void QGraph::setRate(double rate)
{
double Rate;
Rate = static_cast<double>(rate / 100.00);
cur = (cur+1) % length;
RateData[cur] = (1.00 - Rate);
//qDebug() << QString("RateData[%1] : %2").arg(cur).arg(QString::number(RateData[cur],'f',6));
this->update();
}
画背景栅栏
也就是根据背景色,总行数和总列数画线,主要是坐标值的计算,多理解一下就好了。代码如下
QPainter painter(this);
painter.setPen(background_color);
painter.setRenderHint(QPainter::Antialiasing, true); //设置渲染,启动反锯齿
//画背景
graph_heigh = this->height() / ROWS;
graph_width = this->width() / COLS;
for(int row = 0; row < ROWS+1; row++)
{
painter.drawLine(startX,startY+row*graph_heigh,startX+COLS*graph_width,startY+row*graph_heigh);
}
for(int col = 0; col < COLS+1; col++)
{
painter.drawLine(startX+col*graph_width,startY,startX+col*graph_width,startY+ROWS*graph_heigh);
}
画波形线
最近一次更新的数据是cur所标志的数组数据,所以cur+1所指向的数据就是最远一次的数据,我们画图是从左往右画,所以要从最远一次的数据开始,画到最近一次的数据,所以从cur+1的位置往后遍历,一直遍历到cur的位置,就将数组从远到近遍历了一次。
首先设置一下画笔
QPen line_pen;
line_pen.setColor(line_color);
line_pen.setWidth(3);
line_pen.setStyle(Qt::SolidLine);
painter.setPen(line_pen);
开始计算数据
int line_width = this->width() / (COLS*2);
int index = (cur + 1) % length;
QPointF point;
QPainterPath linePath(QPointF(startX-5,this->height()));
for(int i = 0; i < length; i++)
{
point.setX(startX+i*line_width);
point.setY(static_cast<double>((double)(this->height())*RateData[index]));
linePath.lineTo(point);
index = (index+1) % length;
//qDebug() << point;
//qDebug() << QString("%1 RateData[%4]:%5").arg(i).arg(index).arg(QString::number(RateData[index],'f',6));
}
//linePath.lineTo(QPointF(this->width()+5,this->height()));
linePath.lineTo(QPointF(startX+COLS*graph_width,startY+ROWS*graph_heigh));
painter.drawPath(linePath);
通过QPainterPath记录每次经过的点,最后用drawPath将路线绘制出来
最后是颜色的填充
先计算填充的颜色,介于背景色和前景色之间,取中间值
int bg_r,bg_g,bg_b,l_r,l_g,l_b,r,g,b;
line_color.getRgb(&l_r,&l_g,&l_b);
background_color.getRgb(&bg_r,&bg_g,&bg_b);
r = (l_r + bg_r) / 2;
g = (l_g + bg_g) / 2;
b = (l_b + bg_b) / 2;
QColor brush_color(r,g,b,100);
设置画刷
QBrush line_brush;
line_brush.setColor(brush_color);
line_brush.setStyle(Qt::SolidPattern);
将画刷交给画家
painter.setBrush(line_brush);
完成,这是在PC机上运行,所以没有CPU温度
完整的源码放在github上,有需要可以自行下载。 代码名称为190522.zip
https://github.com/ljy980330/opencv_face_sys
有任何问题可以在下面给我留言!大家一起学习!