Qt总结之六:QPaintEvent绘制雷达图

前言

关于雷达样式可参考文章:https://blog.csdn.net/Aidam_Bo/article/details/84260883


一、代码

头文件.h

#ifndef RADARSCAN_H
#define RADARSCAN_H

#include <QtWidgets/QWidget>
#include "ui_radarscan.h"

class RadarScan : public QWidget
{
	Q_OBJECT

public:
	RadarScan(QWidget *parent = 0);
	~RadarScan();

	QPixmap paintWidget();

protected:
	void paintEvent(QPaintEvent *event);
	void resizeEvent(QResizeEvent *event);
	protected slots:
	void timerTimeOut();

private:
	QTimer *timer;
	QPoint point;
	int i_diameter = 0;
	double d_angle = 0;
	QList<QPixmap> list_pixmap;

private:
	Ui::RadarScanClass ui;
};

#endif // RADARSCAN_H

实现.cpp

#include "radarscan.h"
#include <QPainter>
#include <QPen>
#include <QDebug>
#include <QLinearGradient>
#include <QTimer>
#include <QTime>

RadarScan::RadarScan(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	this->setStyleSheet("background-color:black");//设置窗口背景色为黑色
	timer = new QTimer();
	connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));

	timer->start(10);
}

RadarScan::~RadarScan()
{

}
void RadarScan::resizeEvent(QResizeEvent *event)
{
	if (this->width() > this->height()){
		point = QPoint((this->width() - this->height()) / 2 + (this->height() - 12) / 2, this->height() / 2);
		i_diameter = this->height() - 12;
	}
	else{
		point = QPoint(this->width() / 2, (this->height() - this->width()) / 2 + (this->width() - 12) / 2);
		i_diameter = this->width() - 12;
	}
}

void RadarScan::timerTimeOut()
{
	timer->start(10);
	d_angle += 3.14 / 720;
	if (d_angle >= 6.28){
		d_angle = 0;
	}
	update();

}

void RadarScan::paintEvent(QPaintEvent *event)
{
	QPainter p_painter(this);
	//反锯齿
	p_painter.setRenderHint(QPainter::Antialiasing);

	p_painter.drawPixmap(0, 0, this->width(), this->height(), paintWidget());

	QWidget::paintEvent(event);
}

QPixmap RadarScan::paintWidget()
{
	QPixmap pixmap(this->width(), this->height());
	QPainter p_painter(&pixmap);
	QPen pen;
	QTime timedebug;
	timedebug.start();
	//反锯齿
	p_painter.setRenderHint(QPainter::Antialiasing);
	pixmap.fill(Qt::black);

	pen.setColor(Qt::green);
	p_painter.setPen(pen);

	pen.setColor(Qt::gray);
	p_painter.setPen(pen);
	p_painter.drawLine(point.x(), point.y() - i_diameter / 2 - 10, point.x(), point.y() + i_diameter / 2 + 10);//画坐标
	p_painter.drawLine(point.x() - i_diameter / 2 - 10, point.y(), point.x() + i_diameter / 2 + 10, point.y());
	pen.setColor(Qt::green);
	p_painter.setPen(pen);
	for (int i = 0; i<6; i++){
		p_painter.drawEllipse(point.x() - i_diameter*0.2*i / 2, point.y() - i_diameter*0.2*i / 2, i_diameter*0.2*i, i_diameter*0.2*i);
	}

	QConicalGradient conical_gradient(point, (6.28 - d_angle) / 6.28 * 720);//定义圆心和渐变的角度
	conical_gradient.setColorAt(0, Qt::green);
	conical_gradient.setColorAt(0.2, QColor(255, 255, 255, 0));
	p_painter.setBrush(conical_gradient);
	p_painter.drawEllipse(point.x() - i_diameter / 2, point.y() - i_diameter / 2, i_diameter, i_diameter);

	qDebug() << "time_end=" << timedebug.elapsed() << "ms";

	return pixmap;

}

二、细节实现


(1)重写resizeEvent函数,当窗口缩放时,对绘图的大小也进行缩放:

void RadarScan::resizeEvent(QResizeEvent *event)
{
    if(this->width() > this->height()){
        point = QPoint((this->width()-this->height())/2+(this->height()-12)/2,this->height()/2);
        i_diameter = this->height()-12;
    }else{
        point = QPoint(this->width()/2,(this->height()-this->width())/2+(this->width()-12)/2);
        i_diameter = this->width()-12;
    }
}


(2)在绘图函数中主要使用了QPixmap的定义画布,QPEN定义画笔,QConicalGradient对图形进行渐变填充,drawEllipse进行画圆:

QPixmap Widget::paintWidget()
{
    QPixmap pixmap(this->width(),this->height());
    QPainter p_painter(&pixmap);
    QPen pen;
    QTime timedebug;
    timedebug.start();
    //反锯齿
    p_painter.setRenderHint(QPainter::Antialiasing);
    pixmap.fill(Qt::black);
 
    pen.setColor(Qt::green);
    p_painter.setPen(pen);
 
    pen.setColor(Qt::gray);
    p_painter.setPen(pen);
    p_painter.drawLine(point.x(),point.y()-i_diameter/2-10,point.x(),point.y()+i_diameter/2+10);//画坐标
    p_painter.drawLine(point.x()-i_diameter/2-10,point.y(),point.x()+i_diameter/2+10,point.y());
    pen.setColor(Qt::green);
    p_painter.setPen(pen);
    for(int i=0; i<6; i++){
        p_painter.drawEllipse(point.x()-i_diameter*0.2*i/2,point.y()-i_diameter*0.2*i/2,i_diameter*0.2*i,i_diameter*0.2*i);
    }
 
    QConicalGradient conical_gradient(point,(6.28-d_angle)/6.28*720);//定义圆心和渐变的角度
    conical_gradient.setColorAt(0,Qt::green);
    conical_gradient.setColorAt(0.2,QColor(255,255,255,0));
    p_painter.setBrush(conical_gradient);
    p_painter.drawEllipse(point.x()-i_diameter/2,point.y()-i_diameter/2,i_diameter,i_diameter);
 
 
    qDebug()<<"time_end="<<timedebug.elapsed()<<"ms";
 
    return pixmap;
 
}


(3)QTimer定义定时器连接槽函数,当定时溢出时对图像进行刷新,同时重新开启定时,定时单位是毫秒:

void Widget::timerTimeOut()
{
    timer->start(10);
    d_angle += 3.14/720;
    if(d_angle >= 6.28){
        d_angle = 0;
    }
    update();
 
}


(4)最后对paintEven进行重构:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter p_painter(this);
    //反锯齿
    p_painter.setRenderHint(QPainter::Antialiasing);
 
    p_painter.drawPixmap(0,0,this->width(),this->height(),paintWidget());
 
    QWidget::paintEvent(event);
}

三、效果展示


(1)得到的一直在扫描的图像:


(2)打印记录时间:

 


总结

源码:

代码资源下载:https://download.csdn.net/download/aidam_bo/10878728(paintEven绘图)

 

改善:

因为图像会随着窗口的拉伸而变大,当图像变得比较大时,绘图的时间就会变的比较长,图像越大绘图时间越长,看着图像的移动比较缓慢。目前暂时想到了几种简单的思路:

1,使用图片:paintEvent只绘制坐标,扫描的动画使用图片的格式来实现,对图片不断进行旋转,这种方法对图片的透明度有要求。

2,使用多线程:使用多线程同时绘制多个图形,使用信号量对图形进行读取显示。

3,改变渐变填充的区域:这里的渐变填充是填充了整个圆形区域,可以改变填充的区域,使用drawPie绘制扇形进行渐变填充。

4,使用Qt封装的openGL或者第三方库,例如:https://sourceforge.net/projects/qfi/ 这种(这是飞行仪表的开源库,代码很短)。
 

  • 10
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
qPaintEventQt框架中的一个事件类,用于绘制界面上的形元素。而雷达图是一种表达多维数据的形方式,通常用于对比不同数据的相对大小和趋势。 要绘制雷达图,首先需要在界面中创建一个QWidget或QFrame的子类,作为雷达图的容器。在容器的resizeEvent中设置雷达图的大小,并在paintEvent中进行绘制。 在paintEvent中,可以利用QPainter类进行绘制。首先利用QPainter的setRenderHint函数设置抗锯齿,以获得更加平滑的绘制效果。然后可以使用drawPolygon函数画出个体的多边形,根据数据的大小和比例计算各个顶点的坐标。 接着可以通过drawLine函数画出从雷达图中心到顶点的连线,以及连接各个顶点的边线。可以使用drawText函数添加标签和数据值。绘制完成后,可以利用end函数结束绘制。 在绘制雷达图之前,需要根据数据的实际情况确定各个维度的数量和标签,以及计算各个顶点的坐标和连线的位置。可以根据数据的范围和比例,将实际数值映射到雷达图上的坐标系中。 绘制雷达图时,需要考虑美观性和可读性。可以利用颜色、线型、标签等方式来区分和突出显示不同的数据和维度。可以根据需要,添加背景、网格线等装饰元素。 总之,利用qPaintEvent绘制雷达图需要在合适的事件函数中设置绘制的逻辑,并利用QPainter类进行绘制操作。同时需要确定绘制的数据和参数,以及实现绘制时考虑的美观性和可读性。这样可以通过绘制雷达图来直观地展示多维数据的关系和变化趋势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值