QT学习——汽车仪表盘

1.界面预览

2.类的介绍

2.1QPaintEvent

QPaintEvent Qt 框架中一个重要的事件类,专门用于处理绘图事件。当 Qt 视图组件需要重绘自己
的一部分时,就会产生 QPaintEvent 事件。这通常发生在以下几种情况:
1. 窗口第一次显示时 :当窗口或控件第一次出现在屏幕上时,系统会生成一个 QPaintEvent 事件, 通知窗口进行自身的绘制。
2. 窗口大小改变时 :当用户改变窗口的大小时,窗口的内容通常需要重新绘制以适应新的尺寸。
3. 窗口部分被遮挡后又重新显示时 :如果窗口被其他窗口遮挡,然后又重新露出来,被遮挡的部分通 常需要重新绘制。
4. 手动请求重绘 :通过调用 QWidget update() repaint() 方法,可以手动触发重绘事件。
Qt 应用程序中,通常通过重写 QWidget paintEvent(QPaintEvent *) 方法来处理绘制逻辑。
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event) override {
    QPainter painter(this);
    // 绘制逻辑
    }
};

 在 paintEvent 方法中,您可以创建一个 QPainter 对象并使用它来执行绘制操作。 QPainter 可以绘 制各种基本图形,如线条、矩形、椭圆等,还可以绘制文本和图像。重写 paintEvent 是在 Qt 中进行自定义绘制的标准做法

2.2 QPainter

QPainter Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本等。
  •  以下是一些基本的用法示例:
初始化 QPainter :首先,您需要一个 QPaintDevice ,比如一个 QWidget QPixmap ,然后使用它来初始化 QPainter 对象。
QPainter painter(this); // 假设在 QWidget 的子类中
设置画笔和画刷 :您可以设置画笔(用于描边)和画刷(用于填充)的颜色、样式等。
painter.setPen(Qt::blue); // 设置画笔颜色为蓝色
painter.setBrush(Qt::yellow); // 设置画刷颜色为黄色

绘制图形:使用 QPainter 的方法来绘制线条、矩形、圆形、文本等。

painter.drawLine(10, 10, 100, 100); // 画线
painter.drawRect(10, 10, 100, 100); // 画矩形
painter.drawText(10, 10, "Hello, Qt!"); // 画文本

注意, QPainter 的使用依赖于 Qt 的事件循环,因此通常在 QWidget paintEvent 或者类似的事 件处理函数中使用它。如果您在 Qt 应用程序中使用 QPainter ,请确保您遵循 Qt 的事件驱动机制。

2.3线性渐变

QLinearGradient Qt 框架中用于创建线性渐变的类。线性渐变是一种从一个颜色平滑过渡到另一个 颜色的效果,其变化沿着两个点之间的直线进行。这种渐变在图形用户界面设计中非常常见,用于添加 深度、立体感或动态效果
使用 QLinearGradient ,你需要执行以下几个基本步骤:
1. 创建 QLinearGradient 对象 :指定渐变的起点和终点坐标。
2. 设置颜色停靠点 :在渐变线上定义颜色和相应的位置。
3. 使用渐变创建 QBrush :用 QLinearGradient 对象来创建一个 QBrush ,然后用它在 QPainter 中进行绘制。
#include <QPainter>
#include <QLinearGradient>
void MyWidget::paintEvent(QPaintEvent *) {
    // 创建一个 QLinearGradient 对象
    QLinearGradient linearGradient(0, 0, 100, 100); // 起点(0, 0) 终点(100, 100)
    // 设置颜色停靠点
    linearGradient.setColorAt(0.0, Qt::red); // 起点颜色
    linearGradient.setColorAt(1.0, Qt::blue); // 终点颜色
    // 使用这个渐变创建 QBrush
    QBrush brush(linearGradient);
    // 使用 QBrush 进行绘图
    QPainter painter(this);
    painter.setBrush(brush);
    painter.setPen(Qt::NoPen); // 无边框
    painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}
注意事项
QLinearGradient 的颜色变化是沿着两个指定点之间的直线进行的。通过改变这些点的位置,你 可以控制渐变的方向和长度。
setColorAt() 方法的第一个参数是一个介于 0.0 1.0 之间的浮点数,表示颜色在渐变线上的位 置。0.0 通常对应于起点, 1.0 对应于终点。
你可以设置多个颜色停靠点来创建更复杂的渐变效果。例如,你可以在 0.0 处设置一种颜色,在 0.5 处设置另一种颜色,在 1.0 处再设置一种颜色。
使用 QLinearGradient 创建的 QBrush 可以用于填充任何形状,包括矩形、椭圆、多边形等。
为了获取更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
请注意,当窗口小部件的大小发生变化时,渐变的效果可能也会随之改变,除非你相应地调整渐变 的起点和终点坐标或使用其他方法来适应大小变化。

2.4径向渐变 

QRadialGradient Qt 框架中用于创建径向渐变的类。径向渐变是一种从中心点向外部辐射的颜色渐 变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴 影或创建圆形的立体感。
要使用 QRadialGradient ,你需要执行以下几个基本步骤:
1. 创建 QRadialGradient 对象 :指定渐变的中心点、半径以及焦点(可选)。
2. 设置颜色停靠点 :在径向渐变中定义颜色和对应的位置。
3. 使用渐变创建 QBrush :利用 QRadialGradient 对象创建一个 QBrush ,然后用
它在 QPainter 中进行绘制。
#include <QPainter>
#include <QRadialGradient>
void MyWidget::paintEvent(QPaintEvent *) {
    // 创建一个 QRadialGradient 对象
    QRadialGradient radialGradient(50, 50, 50); // 中心和半径 (50, 50, 50)
    // 可选:设置焦点
    // radialGradient.setFocalPoint(30, 30);
    // 设置颜色停靠点
    radialGradient.setColorAt(0.0, Qt::yellow); // 中心颜色
    radialGradient.setColorAt(1.0, Qt::black); // 外围颜色
    // 使用这个渐变创建 QBrush
    QBrush brush(radialGradient);
    // 使用 QBrush 进行绘图
    QPainter painter(this);
    painter.setBrush(brush);
    painter.setPen(Qt::NoPen); // 无边框
    painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}
注意事项:
setColorAt() 方法的第一个参数是一个介于 0.0 1.0 之间的浮点数,表示颜色在径向渐变中的 位置。0.0 通常对应于中心点, 1.0 对应于边缘。
通过添加多个颜色停靠点,你可以创建更复杂的径向渐变效果。
setFocalPoint() 方法允许你设置焦点位置,这是渐变颜色开始变化的点,可以与中心点不同。
使用 QRadialGradient 创建的 QBrush 可以用于 填充任何形状,如矩形、椭圆、多边形等。
为了获得更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
当绘制较大区域时,可以通过调整渐变的半径和中心点来控制渐变效果的扩展
QRadialGradient 非常适用于创建像按钮、指示灯或其他需要有深度感和立体感的界面元素。

 2.5圆锥形渐变

QConicalGradient Qt 框架中用于创建圆锥形渐变的类。圆锥渐变是一种渐变效果,其中颜色沿着 圆锥的轮廓变化,类似于旋转颜色轮。这种渐变以其中心点为基点,颜色沿圆周分布,可以创建出富有 动感的视觉效果
使用 QConicalGradient ,你通常需要做以下几个步骤:
1. 创建 QConicalGradient 对象 :指定渐变的中心点和起始角度。
2. 设置颜色停靠点 :为渐变添加不同的颜色和对应的位置(角度)。
3. 使用渐变创建 QBrush :使用这个渐变对象来创建一个 QBrush ,然后应用到 QPainter 中进行绘
图。
#include <QPainter>
#include <QConicalGradient>
void MyWidget::paintEvent(QPaintEvent *) {
    // 创建一个 QConicalGradient 对象
    QConicalGradient conicalGradient(100, 100, 0); // 中心点 (100, 100),起始角度 0
    // 添加颜色停靠点
    conicalGradient.setColorAt(0.0, Qt::red);
    conicalGradient.setColorAt(0.5, Qt::blue);
    conicalGradient.setColorAt(1.0, Qt::red);
    // 使用这个渐变创建 QBrush
    QBrush brush(conicalGradient);
    // 使用 QBrush 进行绘图
    QPainter painter(this);
    painter.setBrush(brush);
    painter.setPen(Qt::NoPen); // 无边框
    painter.drawRect(this->rect()); // 绘制矩形覆盖整个小部件
}
注意事项:
QConicalGradient 的颜色是沿着圆周分布的,其中 0.0 1.0 在圆周上是相同的位置。
你可以通过添加多个颜色停靠点来创建更复杂的渐变效果。
QConicalGradient 在使用时,角度是按照顺时针方向测量的,起始点(0 度)通常在三点钟方向。
为了达到最佳的渲染效果,可以启用 QPainter 的抗锯齿渲染提示 ( QPainter::Antialiasing )。
QConicalGradient 非常适合用于创建旋转或动态效果的图形,例如加载指示器、进度条或任何需 要圆周颜色变化的场景。

3.代码分析 

在仪表盘的刻度下画出迈速数值

1.首先要确定迈速数值坐标的位置。

2.将坐标系移动到确定好的x,y上。

3.画上迈速数值。

通过一个简单的数学计算x=cosA*圆的半径y=sinA*圆的半径就可以确定坐标的位置。

A 同过210°这个大角减去这个位置之前刻度的度数值就可以得到

  • 这样就可以确定迈速数值坐标的位置,一下是代码的实现,剩下的代码比较简单就不多介绍了。
//画刻度的文字
void Widget::drawScaleText(QPainter &painter, int radius)
{
    QFont font("Arial", 15);
    painter.save();
    font.setBold(true);
    painter.setFont(font);
    int r = radius - 42;
    for(int i = 0; i <= 60; i++){
        if(i % 5 == 0){
            //保存坐标
            painter.save();
            //确定x,y坐标
            int delx = qCos(qDegreesToRadians(210 - (Angle * i))) * r;
            int dely = qSin(qDegreesToRadians(210 - (Angle * i))) * r;
            //将坐标系移动到x,y坐标上
            painter.translate(QPoint(delx, -dely));
            //旋转一下
            painter.rotate(-120 + Angle*i);//Angle=4 30*4=120 实参为0
            //写上文字
            painter.drawText(-20, -20, 40, 40, Qt::AlignCenter, QString::number(i*4));
            //回复坐标
            painter.restore();
        }
    }
}

4.完整代码

4.1widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QPaintEvent>
#include <QTimer>
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent *event) override;

private:
    Ui::Widget *ui;
    QTimer *timer;
    int currentValue;
    int mark;
    double Angle;
    int StartAngle;

    //初始化画布 让背景为黑色
    void initCanvas(QPainter& painter);
    //画中间的小圆
    void drawMiddleCircle(QPainter &painter, int radius);
    //画出当前的速度
    void drawCurrentSpeed(QPainter &painter);
    //画刻度
    void drawScale(QPainter &painter, int radius);
    //画刻度的文字
    void drawScaleText(QPainter &painter, int radius);
    //画指针
    void drawPointLen(QPainter &painter, int len);
    //画扇形
    void drawSpeedPie(QPainter &painter, int radius);
    //在中间画一个黑色的圆圈
    void drawCircleBlack(QPainter &painter, int radius);
    //在中间画一个渐变的红色
    void drawCircleRed(QPainter &painter, int radius);
    //最外圈渐变色
    void drawOutCircle(QPainter &painter, int radius);
    //画一个宝马logo
    void drawLogo(QPainter &painter, int radius);
};
#endif // WIDGET_H

4.2widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QPainter>
#include <QtMath>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setFixedSize(800, 600);

    timer = new QTimer(this);
    currentValue = 0;
    mark = 0;
    StartAngle = 150;

    connect(timer, &QTimer::timeout,[=](){
        currentValue += (mark == 0) ? 1 : -1;
        if (currentValue >= 60) mark = 1;
        if (currentValue == 0)  mark = 0;

        update();
    });
    timer->start(50);
}

Widget::~Widget()
{
    delete ui;
}

// 初始化画布 让背景为黑色
void Widget::initCanvas(QPainter &painter)
{
    // 设置抗锯齿渲染
    painter.setRenderHint(QPainter::Antialiasing,true);

    // 设置画刷为黑色,绘制整个窗口的矩形
    painter.setBrush(Qt::black);
    painter.drawRect(rect());

    // 将坐标原点移动到窗口中心向下一点
    painter.translate(rect().width()/2, rect().height()*0.6);
}

// 画中间的小圆
void Widget::drawMiddleCircle(QPainter &painter, int radius)
{
    // 画小圆
    painter.setBrush(Qt::NoBrush);
    painter.setPen(QPen(Qt::white, 3));
    painter.drawEllipse(QPoint(0,0), radius, radius);
}

//画出当前的速度
void Widget::drawCurrentSpeed(QPainter &painter)
{
    // 设置字体样式
    QFont font("Arial", 30);// 创建字体对象,Arial 字体,大小 30
    font.setBold(true);// 设置字体为粗体
    painter.setFont(font);// 在绘图设备上设置字体
    painter.setPen(Qt::white); // 设置画笔颜色为白色
    painter.drawText(QRect(-60, -60, 120, 70), Qt::AlignCenter, QString::number(currentValue*4));// 在指定矩形区域内绘制文本,居中显示当前速度值

    QFont _font("Arial", 15);
    _font.setBold(true);
    painter.setFont(_font);
    painter.setPen(Qt::white);
    painter.drawText(QRect(-60, -60, 120, 145), Qt::AlignCenter, "Km/h");
}

//画刻度
void Widget::drawScale(QPainter &painter, int radius)
{
    //计算角度
    Angle = 240*1.0 / 60;

    painter.setPen(QPen(Qt::white, 4));
    painter.save();
    painter.rotate(StartAngle);
    //绘制刻度
    for(int i = 0; i<=60; i++){
        if(i >= 40){
            painter.setPen(QPen(Qt::red,4));
        }
        if(i % 5 == 0){
            painter.drawLine(radius - 20, 0, radius - 2, 0);//画长刻度线
        }else{
            painter.drawLine(radius - 8, 0,  radius - 2, 0);//画短刻度线
        }
        painter.rotate(Angle);//旋转坐标
    }
    painter.restore();
    painter.setPen(Qt::white);

}

//画刻度的文字
void Widget::drawScaleText(QPainter &painter, int radius)
{
    QFont font("Arial", 15);
    painter.save();
    font.setBold(true);
    painter.setFont(font);
    int r = radius - 42;
    for(int i = 0; i <= 60; i++){
        if(i % 5 == 0){
            //保存坐标
            painter.save();
            //确定x,y坐标
            int delx = qCos(qDegreesToRadians(210 - (Angle * i))) * r;
            int dely = qSin(qDegreesToRadians(210 - (Angle * i))) * r;
            //将坐标系移动到x,y坐标上
            painter.translate(QPoint(delx, -dely));
            //旋转一下
            painter.rotate(-120 + Angle*i);//Angle=4 30*4=120 实参为0
            //写上文字
            painter.drawText(-20, -20, 40, 40, Qt::AlignCenter, QString::number(i*4));
            //回复坐标
            painter.restore();
        }
    }
}

//画指针
void Widget::drawPointLen(QPainter &painter, int len)
{

    painter.restore();
    painter.save();//保存当前的坐标点 指针指向3点钟方向

    painter.setBrush(Qt::white);
    painter.setPen(Qt::NoPen);
    static const QPointF points[4] = {//设置指针形状的坐标
                                      QPointF(0.0, 0.0),
                                      QPointF(249.0, -1.1),
                                      QPointF(249.0, 1.1),
                                      QPointF(0.0, 15.0)
                                     };
    painter.rotate(StartAngle + Angle*currentValue);//指针初始化位置
    painter.drawPolygon(points, 4);
    //painter.drawLine(60, 0, len, 0);
    painter.restore();//恢复之前保存的状态
}

//画扇形
void Widget::drawSpeedPie(QPainter &painter, int radius)
{
    //painter.restore();
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(255, 0, 0, 100));
    painter.drawPie(QRect(-radius, -radius , radius*2, radius*2), (-StartAngle)*16, -Angle*currentValue*16);//Angle加符号让指针顺时针画
}

//在中间画一个黑色的圆
void Widget::drawCircleBlack(QPainter &painter, int radius)
{
    painter.setBrush(Qt::black);
    painter.drawEllipse(QPoint(0, 0),radius,radius);
}

//在中间画一个渐变的红色
void Widget::drawCircleRed(QPainter &painter, int radius)
{
    QRadialGradient radialGradient(0, 0, 105);
    // 设置颜色停靠点
    radialGradient.setColorAt(0.0, QColor(255,0,0,200)); // 中心颜色
    radialGradient.setColorAt(1.0, QColor(0,0,0,100)); // 外围颜色
    painter.setBrush(QBrush(radialGradient));
    painter.drawEllipse(QPoint(0, 0), radius, radius);
}

//最外圈渐变色
void Widget::drawOutCircle(QPainter &painter, int radius)
{
    //painter.restore();
    painter.setPen(Qt::NoPen);// 设置画笔为无边框
    QRadialGradient radialGradient(0, 0, radius);// 创建一个径向渐变,中心在 (0, 0),半径为 radius
    // 设置径向渐变的颜色停止点和颜色
    // 完全不透明的红色,alpha 值为 200
    radialGradient.setColorAt(1.0, QColor(255,0,0,200));
    radialGradient.setColorAt(0.97, QColor(255,0,0,120));// 略微透明的红色,alpha 值为 120
    radialGradient.setColorAt(0.9, QColor(0,0,0,0));// 完全透明的黑色
    radialGradient.setColorAt(0, QColor(0,0,0,0));// 完全透明的黑色
    painter.setBrush(QBrush(radialGradient));// 设置画刷为径向渐变
    painter.drawPie(QRect(-radius, -radius , radius*2, radius*2), -150*16, -Angle*60*16);//Angle加符号让指针顺时针画
}

//画一个宝马logo
void Widget::drawLogo(QPainter &painter, int radius)
{
    painter.drawPixmap(QRect(-45, radius*0.3, 100, 95), QPixmap(":/baoma.png"));//在一个矩形里画一个logo
}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    //初始化画布 让背景为黑色
    initCanvas(painter);
    //画中间的小圆
    drawMiddleCircle(painter, 60);
    //画刻度
    drawScale(painter, height()/2);
    //画刻度的文字
    drawScaleText(painter, height()/2);
    //画指针
    drawPointLen(painter, height()/2 - 48);
    //画扇形
    drawSpeedPie(painter, height()/2 + 25);
    //在中间画一个渐变的红色
    drawCircleRed(painter, 110);
    //在中间画一个黑色的圆圈
    drawCircleBlack(painter, 80);
    //画出当前的速度
    drawCurrentSpeed(painter);
    //最外圈渐变色
    drawOutCircle(painter, height()/2 + 25);
    //画一个宝马logo
    drawLogo(painter, height()/2);
}

 

  • 23
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值