代码一步一步讲,就不写用啥之类的了,暗部走来,自己找使用的类以及使用方法
1、创建工程
2、重载paintEvent
#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
protected:
virtual void paintEvent(QPaintEvent *event);
void MainWindow::paintEvent(QPaintEvent *event)
{
}
3、构建绘画对象,调整表盘位置、画笔位置、刷子之类的
//创建对象
QPainter m_painter(this);
//表盘宽度不变,高度-100,中心位置在前面两个小的的中间
int m_width = this->width();
int m_height = this->height() - 100;
int radius = ((m_width > m_height)?m_height:m_width)/2.0;
//移动画笔到中下方位置
m_painter.translate(m_width/2,m_height*0.6);
//启用反锯齿
m_painter.setRenderHint(QPainter::Antialiasing, true);
m_painter.setPen(Qt::NoPen);
//设置画刷颜色
m_painter.setBrush(QColor(138,43,226));
4、画刻度线
//刻度线
DrawSmallScale(m_painter, radius - 60);
private:
void DrawSmallScale(QPainter & painter, int radius);
void MainWindow::DrawSmallScale(QPainter & painter, int radius)
{
//组装点路径图(刻度)
QPainterPath pointPath_small;
pointPath_small.moveTo(-2, -2);
pointPath_small.lineTo(2, -2);
pointPath_small.lineTo(2, 8);
pointPath_small.lineTo(-2, 8);
QPainterPath pointPath_big;
pointPath_big.moveTo(-2, -2);
pointPath_big.lineTo(2, -2);
pointPath_big.lineTo(2, 20);
pointPath_big.lineTo(-2, 20);
//绘制61个小点
for(int i = 0; i < 121; i += 2)
{
QPointF point(0, 0);
painter.save();
point.setX(radius* qCos(((210-i*2)*M_PI)/180));
point.setY(radius* qSin(((-210+i*2)*M_PI)/180));
painter.translate(point.x(), point.y());
painter.rotate(-120+i*2);
if(i<80)
{
painter.setBrush(QColor(0, 0, 0));
}
if(i>=80)
{
painter.setBrush(QColor(235, 70, 70));
}
if(i%5 == 0)
{
painter.drawPath(pointPath_big);//绘画大刻度
}
else
{
painter.drawPath(pointPath_small);//绘画小刻度
}
painter.restore();
}
}
5、刻度数字
//刻度数字
DrawDigital(m_painter, radius - 90);
void DrawDigital(QPainter & painter, int radius);
void MainWindow::DrawDigital(QPainter &painter, int radius)
{
//设置画笔,画笔默认NOPEN
painter.setPen(QColor(0, 0, 0));
QFont font;
font.setFamily("Arical");
font.setPointSize(15);
font.setBold(true);
painter.setFont(font);
for(int i=0;i<13;++i)
{
QPointF point(0, 0);
painter.save();
point.setX(radius* qCos(((210-i*20)*M_PI)/180));
point.setY(radius* qSin(((210-i*20)*M_PI)/180));
painter.translate(point.x(), -point.y());
painter.rotate(-120+i*20);
painter.drawText(-25, 0, 50, 20, Qt::AlignCenter, QString::number(i*20));
painter.restore();
}
//还原画笔
painter.setPen(Qt::NoPen);
}
6、逐渐发光外扇形
/*所有形状绘画*/
//逐渐发光外扇形
DrawCircle(m_painter, radius - 35);
void DrawCircle(QPainter & painter, int radius);
void MainWindow::DrawCircle(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath outRing;
QPainterPath inRing;
outRing.moveTo(0,0);
inRing.moveTo(0,0);
outRing.arcTo(-radius, -radius, 2*radius, 2*radius, -30, 240);
inRing.addEllipse(-radius+50, -radius+50, 2*(radius-50), 2*(radius-50));
outRing.closeSubpath();
//设置渐变色
QRadialGradient radialGradient(0,0,radius,0,0);
radialGradient.setColorAt(1, QColor(0,82,199));
radialGradient.setColorAt(0.92, Qt::transparent);
//设置画刷
painter.setBrush(radialGradient);
//大圆减小圆
painter.drawPath(outRing.subtracted(inRing));
//恢复
painter.restore();
}
7、指针
void DrawPointer(QPainter & painter, int radius);
//指针
DrawPointer(m_painter, radius-130);
void MainWindow::DrawPointer(QPainter &painter, int radius)
{
//组装点路径图
QPainterPath pointPath;
pointPath.moveTo(10,0);
pointPath.lineTo(1,-radius);
pointPath.lineTo(-1,-radius);
pointPath.lineTo(-10,0);
pointPath.arcTo(-10,0,20,20,180,180);
QPainterPath inRing;
inRing.addEllipse(-5,-5,10,10);
painter.save();
//计算并选择绘图对象坐标
painter.rotate(degRotate-120);
painter.setBrush(QColor(255,0,0));
painter.drawPath(pointPath.subtracted(inRing));
painter.restore();
}
8、最外细圆圈
void DrawCircle_line(QPainter & painter, int radius);
//最外细圆圈
DrawCircle_line(m_painter, radius-35);
void MainWindow::DrawCircle_line(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath outRing;
QPainterPath inRing;
outRing.moveTo(0,0);
inRing.moveTo(0,0);
outRing.arcTo(-radius,-radius,2*radius,2*radius,-30,240);
inRing.addEllipse(-radius+2,-radius+2,2*(radius-2),2*(radius-2));
outRing.closeSubpath();
//设置画刷
painter.setBrush(QColor(5,228,255));
//大圆减小圆
painter.drawPath(outRing.subtracted(inRing));
painter.restore();
}
9、中间大圆
void DrawCircle_bom_big(QPainter & painter, int radius);
//中间大圆
DrawCircle_bom_big(m_painter, radius-150);
void MainWindow::DrawCircle_bom_big(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath inRing;
inRing.moveTo(0,0);
inRing.addEllipse(-radius+50,-radius+50,2*(radius-50),2*(radius-50));
//设置画刷
painter.setBrush(QColor(10,20,30));
painter.drawPath(inRing);
painter.restore();
}
10、逐渐发光内圈
void DrawCircle_bom_shine(QPainter & painter, int radius);
//逐渐发光内圈
DrawCircle_bom_shine(m_painter, radius-230);
void MainWindow::DrawCircle_bom_shine(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//渐变色
QRadialGradient radialGradient(0,0,radius,0,0);
radialGradient.setColorAt(0.5,QColor(10,68,185,150));
radialGradient.setColorAt(1.0,Qt::transparent);
painter.setBrush(QBrush(radialGradient));
painter.drawRect(-radius,-radius,2*radius,2*radius);
painter.restore();
}
11、中间小圆
void DrawCircle_bom_small(QPainter & painter, int radius);
//中间小圆
DrawCircle_bom_small(m_painter, radius-200);
void MainWindow::DrawCircle_bom_small(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath inRing;
inRing.moveTo(0,0);
inRing.addEllipse(-radius+50,-radius+50,2*(radius-50),2*(radius-50));
//设置画刷
painter.setBrush(QColor(10,20,30));
painter.drawPath(inRing);
painter.restore();
}
12、动态扇形环
void DrawCircle_arc(QPainter & painter, int radius);
//动态扇形环
DrawCircle_arc(m_painter, radius-40);
void MainWindow::DrawCircle_arc(QPainter &painter, int radius)
{
QRect rect(-radius, -radius, 2*radius, 2*radius);
QConicalGradient Conical(0,0,-70);
Conical.setColorAt(0.1, QColor(255,88,127,200));//红色
Conical.setColorAt(0.5, QColor(53,179,251,150));//蓝色
painter.setBrush(Conical);
painter.drawPie(rect, 210*16, -(degRotate)*16);
}
由于是动态的,需要加入定时器与按键事件模拟加减速
13、单位与时速
固定下窗口大小
setFixedSize(1280,800);
定义一些全局变量
private:
int degRotate = 0;
int radius;//仪表盘中心位置
int direction;//指针运动的方向,1为前进,0为后退
画表盘文字
void DrawUnit(QPainter & painter, int radius);
void DrawNum(QPainter & painter, int radius);
//单位
DrawUnit(m_painter,radius-390);
//时速
DrawNum(m_painter,radius-300);
void MainWindow::DrawUnit(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//设置笔
painter.setPen(QColor(255,255,255));
//设置字体
QFont font;
font.setFamily("Arial");
font.setPointSize(16);
font.setBold(true);
painter.setFont(font);
//画文字
painter.drawText(-50,-radius,100,20,Qt::AlignCenter,QString("km/h"));
painter.setPen(QColor(0,0,0));
painter.drawText(-60,-radius+130,120,40,Qt::AlignCenter,QString("当前车速"));
painter.setPen(QColor(0,0,0,50));
painter.drawText(-120,-radius+280,250,40,Qt::AlignCenter,QString("-请按space键加速-"));
painter.restore();
}
void MainWindow::DrawNum(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//设置笔
painter.setPen(QColor(255,255,255));
//设置字体
QFont font;
font.setFamily("Arial");
font.setPointSize(45);
painter.setFont(font);
//写文字
painter.drawText(-75,-radius-20,150,100,Qt::AlignCenter,QString::number(degRotate));
painter.restore();
}
14、按键事件
添加定时器和按键事件的头文件
#include <QTimer>
#include <QKeyEvent>
重写按键虚函数
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(event->key() == Qt::Key_Space)
{
if(direction == 0)
{
myTimer->start(1);
direction = 1;
}
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if(event->key() == Qt::Key_Space)
direction = 0;
}
构建定时器对象
private:
int degRotate = 0;
int radius;//仪表盘中心位置
int direction;//指针运动的方向,1为前进,0为后退
QTimer *myTimer;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setFixedSize(1280,800);
//定时器
myTimer = new QTimer(this);
connect(myTimer, SIGNAL(timeout()), this, SLOT(slot_seed_changed()));
}
新建速度变化的槽函数
private slots:
void slot_seed_changed();
void MainWindow::slot_seed_changed()
{
if(direction == 1)//加速
{
degRotate++;
if(degRotate > 240)
{
degRotate = 240;
}
}
else if(direction == 0)//减速
{
degRotate--;
if(degRotate<0)
{
degRotate = 0;
myTimer->stop();
}
}
update();//刷新画面
}
15、动画效果
汽车仪表盘
16、完整代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QtMath>
#include <QTimer>
#include <QKeyEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void keyPressEvent(QKeyEvent *event);
virtual void keyReleaseEvent(QKeyEvent *event);
private:
void DrawSmallScale(QPainter & painter, int radius);
void DrawDigital(QPainter & painter, int radius);
void DrawCircle(QPainter & painter, int radius);
void DrawCircle_arc(QPainter & painter, int radius);
void DrawPointer(QPainter & painter, int radius);
void DrawCircle_line(QPainter & painter, int radius);
void DrawCircle_bom_big(QPainter & painter, int radius);
void DrawCircle_bom_shine(QPainter & painter, int radius);
void DrawCircle_bom_small(QPainter & painter, int radius);
void DrawUnit(QPainter & painter, int radius);
void DrawNum(QPainter & painter, int radius);
private:
int degRotate = 0;
int radius;//仪表盘中心位置
int direction;//指针运动的方向,1为前进,0为后退
QTimer *myTimer;
private slots:
void slot_seed_changed();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setFixedSize(1280,800);
//定时器
myTimer = new QTimer(this);
connect(myTimer, SIGNAL(timeout()), this, SLOT(slot_seed_changed()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *event)
{
//创建对象
QPainter m_painter(this);
//表盘宽度不变,高度-100,中心位置在前面两个小的的中间
int m_width = this->width();
int m_height = this->height() - 100;
int radius = ((m_width > m_height)?m_height:m_width)/2.0;
//移动画笔到中下方位置
m_painter.translate(m_width/2,m_height*0.6);
//启用反锯齿
m_painter.setRenderHint(QPainter::Antialiasing, true);
m_painter.setPen(Qt::NoPen);
//设置画刷颜色
m_painter.setBrush(QColor(138,43,226));
//刻度线
DrawSmallScale(m_painter, radius - 60);
//刻度数字
DrawDigital(m_painter, radius - 90);
/*所有形状绘画*/
//逐渐发光外扇形
DrawCircle(m_painter, radius - 35);
//动态扇形环
DrawCircle_arc(m_painter, radius-40);
//指针
DrawPointer(m_painter, radius-130);
//最外细圆圈
DrawCircle_line(m_painter, radius-35);
//中间大圆
DrawCircle_bom_big(m_painter, radius-150);
//逐渐发光内圈
DrawCircle_bom_shine(m_painter, radius-230);
//中间小圆
DrawCircle_bom_small(m_painter, radius-200);
//单位
DrawUnit(m_painter,radius-390);
//时速
DrawNum(m_painter,radius-300);
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Space)
{
if(direction == 0)
{
myTimer->start(1);
direction = 1;
}
}
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Space)
direction = 0;
}
void MainWindow::DrawSmallScale(QPainter & painter, int radius)
{
//组装点路径图(刻度)
QPainterPath pointPath_small;
pointPath_small.moveTo(-2, -2);
pointPath_small.lineTo(2, -2);
pointPath_small.lineTo(2, 8);
pointPath_small.lineTo(-2, 8);
QPainterPath pointPath_big;
pointPath_big.moveTo(-2, -2);
pointPath_big.lineTo(2, -2);
pointPath_big.lineTo(2, 20);
pointPath_big.lineTo(-2, 20);
//绘制61个小点
for(int i = 0; i < 121; i += 2)
{
QPointF point(0, 0);
painter.save();
point.setX(radius* qCos(((210-i*2)*M_PI)/180));
point.setY(radius* qSin(((-210+i*2)*M_PI)/180));
painter.translate(point.x(), point.y());
painter.rotate(-120+i*2);
if(i<80)
{
painter.setBrush(QColor(0, 0, 0));
}
if(i>=80)
{
painter.setBrush(QColor(235, 70, 70));
}
if(i%5 == 0)
{
painter.drawPath(pointPath_big);//绘画大刻度
}
else
{
painter.drawPath(pointPath_small);//绘画小刻度
}
painter.restore();
}
}
void MainWindow::DrawDigital(QPainter &painter, int radius)
{
//设置画笔,画笔默认NOPEN
painter.setPen(QColor(0, 0, 0));
QFont font;
font.setFamily("Arical");
font.setPointSize(15);
font.setBold(true);
painter.setFont(font);
for(int i=0;i<13;++i)
{
QPointF point(0, 0);
painter.save();
point.setX(radius* qCos(((210-i*20)*M_PI)/180));
point.setY(radius* qSin(((210-i*20)*M_PI)/180));
painter.translate(point.x(), -point.y());
painter.rotate(-120+i*20);
painter.drawText(-25, 0, 50, 20, Qt::AlignCenter, QString::number(i*20));
painter.restore();
}
//还原画笔
painter.setPen(Qt::NoPen);
}
void MainWindow::DrawCircle(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath outRing;
QPainterPath inRing;
outRing.moveTo(0,0);
inRing.moveTo(0,0);
outRing.arcTo(-radius, -radius, 2*radius, 2*radius, -30, 240);
inRing.addEllipse(-radius+50, -radius+50, 2*(radius-50), 2*(radius-50));
outRing.closeSubpath();
//设置渐变色
QRadialGradient radialGradient(0,0,radius,0,0);
radialGradient.setColorAt(1, QColor(0,82,199));
radialGradient.setColorAt(0.92, Qt::transparent);
//设置画刷
painter.setBrush(radialGradient);
//大圆减小圆
painter.drawPath(outRing.subtracted(inRing));
//恢复
painter.restore();
}
void MainWindow::DrawCircle_arc(QPainter &painter, int radius)
{
QRect rect(-radius, -radius, 2*radius, 2*radius);
QConicalGradient Conical(0,0,-70);
Conical.setColorAt(0.1, QColor(255,88,127,200));//红色
Conical.setColorAt(0.5, QColor(53,179,251,150));//蓝色
painter.setBrush(Conical);
painter.drawPie(rect, 210*16, -(degRotate)*16);
}
void MainWindow::DrawPointer(QPainter &painter, int radius)
{
//组装点路径图
QPainterPath pointPath;
pointPath.moveTo(10,0);
pointPath.lineTo(1,-radius);
pointPath.lineTo(-1,-radius);
pointPath.lineTo(-10,0);
pointPath.arcTo(-10,0,20,20,180,180);
QPainterPath inRing;
inRing.addEllipse(-5,-5,10,10);
painter.save();
//计算并选择绘图对象坐标
painter.rotate(degRotate-120);
painter.setBrush(QColor(255,0,0));
painter.drawPath(pointPath.subtracted(inRing));
painter.restore();
}
void MainWindow::DrawCircle_line(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath outRing;
QPainterPath inRing;
outRing.moveTo(0,0);
inRing.moveTo(0,0);
outRing.arcTo(-radius,-radius,2*radius,2*radius,-30,240);
inRing.addEllipse(-radius+2,-radius+2,2*(radius-2),2*(radius-2));
outRing.closeSubpath();
//设置画刷
painter.setBrush(QColor(5,228,255));
//大圆减小圆
painter.drawPath(outRing.subtracted(inRing));
painter.restore();
}
void MainWindow::DrawCircle_bom_big(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath inRing;
inRing.moveTo(0,0);
inRing.addEllipse(-radius+50,-radius+50,2*(radius-50),2*(radius-50));
//设置画刷
painter.setBrush(QColor(10,20,30));
painter.drawPath(inRing);
painter.restore();
}
void MainWindow::DrawCircle_bom_shine(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//渐变色
QRadialGradient radialGradient(0,0,radius,0,0);
radialGradient.setColorAt(0.5,QColor(10,68,185,150));
radialGradient.setColorAt(1.0,Qt::transparent);
painter.setBrush(QBrush(radialGradient));
painter.drawRect(-radius,-radius,2*radius,2*radius);
painter.restore();
}
void MainWindow::DrawCircle_bom_small(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//计算大小圆路径
QPainterPath inRing;
inRing.moveTo(0,0);
inRing.addEllipse(-radius+50,-radius+50,2*(radius-50),2*(radius-50));
//设置画刷
painter.setBrush(QColor(10,20,30));
painter.drawPath(inRing);
painter.restore();
}
void MainWindow::DrawUnit(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//设置笔
painter.setPen(QColor(255,255,255));
//设置字体
QFont font;
font.setFamily("Arial");
font.setPointSize(16);
font.setBold(true);
painter.setFont(font);
//画文字
painter.drawText(-50,-radius,100,20,Qt::AlignCenter,QString("km/h"));
painter.setPen(QColor(0,0,0));
painter.drawText(-60,-radius+130,120,40,Qt::AlignCenter,QString("当前车速"));
painter.setPen(QColor(0,0,0,50));
painter.drawText(-120,-radius+280,250,40,Qt::AlignCenter,QString("-请按space键加速-"));
painter.restore();
}
void MainWindow::DrawNum(QPainter &painter, int radius)
{
//保存绘图对象
painter.save();
//设置笔
painter.setPen(QColor(255,255,255));
//设置字体
QFont font;
font.setFamily("Arial");
font.setPointSize(45);
painter.setFont(font);
//写文字
painter.drawText(-75,-radius-20,150,100,Qt::AlignCenter,QString::number(degRotate));
painter.restore();
}
void MainWindow::slot_seed_changed()
{
if(direction == 1)//加速
{
degRotate++;
if(degRotate > 240)
{
degRotate = 240;
}
}
else if(direction == 0)//减速
{
degRotate--;
if(degRotate<0)
{
degRotate = 0;
myTimer->stop();
}
}
update();//刷新画面
}