QT自定义简单表盘(完整代码)

运行结果:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
      m_wgt_mileage =new QWidget(this);

      m_minSpeed=0;
      m_maxSpeed=3000;

      m_startAngle=150;

      m_refSize=200;

      m_radius=100;

      m_curSpeed=0;

      m_endAngle=30;

      m_anglePerVel =5;

}

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

void Widget::paintEvent(QPaintEvent */*event*/)
{




    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  //设置反走样

    float scale = qMin(width(),height());
    //设置缩放比例和原点的先后顺序很重要
    painter.scale(scale/(m_refSize*4),scale/(m_refSize*4));
    painter.translate(m_refSize,m_refSize); //设置坐标原点
 //  painter.translate(m_refSize,m_refSize);


    drawFrame(painter); //绘制边框
    drawDividing(painter);//绘制刻度
    drawNumberIndicator(painter);//绘制指示数字
    drawNumberSpeed(painter);//显示数字速度
    drawIndicator(painter);//绘制速度指针

    m_wgt_mileage->setGeometry((width() - m_wgt_mileage->width()) / 2 + 30,height() - m_wgt_mileage->height() - 60,m_wgt_mileage->width(),m_wgt_mileage->height());


}

//绘制边框
void Widget::drawFrame(QPainter &painter)
{


    painter.save();  //保存原点位置
    painter.setPen(Qt::NoPen);//确保没有边框线----填满,不留边界线

    QLinearGradient lg1(-m_radius,-m_radius,m_radius,m_radius);//线性渐变 渐变区域
    lg1.setColorAt(0,Qt::blue); //0是停止点,用于渐变
    lg1.setColorAt(1,Qt::green);
    lg1.setSpread(QGradient::ReflectSpread);//渐变样式(颜色传播样式)

    painter.setBrush(lg1);   //画笔填充物
    painter.drawEllipse(-m_radius,-m_radius,m_refSize,m_refSize);//画笔绘画,绘制一个椭圆------>画完会回到原点

    //-------------画个小圆----------------//
    painter.setBrush(Qt::black);
    painter.drawEllipse(QPoint(0,0),90,90);//画出小圆半径
    painter.restore();
}

//绘制刻度(主要用了 Qpainter::rotate)
void Widget::drawDividing(QPainter &painter)
{
    painter.save();

    painter.rotate(m_startAngle);//将坐标系顺时针旋转150°,到达起始位置

    QPen pen(Qt::white);
    painter.setPen(pen);
    painter.drawLine(88,0,80,0);


    int step = (m_maxSpeed - m_minSpeed) / 50;  //每一个线条之间距离5
    double angleStep = (360.0 - (m_startAngle - m_endAngle)) / step;  //坐标系每走一步旋转的角度  360 - (开始角度 - 结束角度)/每次转的间隔

    m_anglePerVel = angleStep;
    for (int i = m_minSpeed; i <= m_maxSpeed; i += 50)
    {
        if (i >= 0){ //绘制红色
            pen.setColor(Qt::red);
            painter.setPen(pen);
        }

        if (i % 250 == 0){//粗线
            pen.setWidth(2);
            painter.setPen(pen);
            painter.drawLine(88,0,75,0);

        }else if (i % 250 == 0){//中等
            pen.setWidth(1);
            painter.setPen(pen);
            painter.drawLine(88,0,80,0);

        }else if (i % 50 == 0){ //短线
            pen.setWidth(0);
            painter.setPen(pen);
            painter.drawLine(83,0,80,0);
        }


        painter.rotate(angleStep);  //在之前的基础上原点坐标旋转angleStep度
    }


    painter.restore();
}

/**
圆点坐标:(x0,y0)
半径:r
角度:a0

则圆上任一点为:(x1,y1)
x1   =   x0   +   r   *   cos(ao   *   3.14   /180   )
y1   =   y0   +   r   *   sin(ao   *   3.14   /180   )

*/

//绘制数字指示
void Widget::drawNumberIndicator(QPainter &painter)
{
    painter.save();//(100,100)

    painter.setPen(Qt::red);

    double x,y;
    QFontMetricsF fm(this->font());//获取字体
    painter.setFont(QFont("Arial",3));//改变显示字体、字号
    painter.setPen(Qt::white);



    int anglestart = 150;
    int step = (m_maxSpeed - m_minSpeed)/250;
    double angleStep = (360.0 - (m_startAngle - m_endAngle)) / step;
    for (int i = 0; i <= 12; i++)//每隔250Km设置一个数字
    {
        double textWidth = fontMetrics().width("1");
        double textHeight = fontMetrics().height();
        qDebug()<<textWidth<<","<<textHeight;
        x  =0+75* cos((anglestart *3.14)/180) -textWidth/2;
        y  =0+75* sin((anglestart *3.14)/180)+textHeight/2;

        QString value = QString::number(i*250);//设置显示数字
        painter.drawText(x,y,value);
       // painter.drawPoint(x,y);
        anglestart+=(angleStep*1);

    }

    painter.restore();
}

//显示KM/H
///
/// painter::drawText
///
void Widget::drawNumberSpeed(QPainter &painter)
{
    painter.save();
       painter.setPen(Qt::white);
       QString speed = QString("%1 km/h").arg(m_curSpeed*50);
       QFontMetricsF fm(this->font());
       qreal w = fm.size(Qt::TextSingleLine,speed).width(); //TextSingleLine 忽略换行符,返回给定文本中字符的大小(以像素为单位)
       painter.drawText(-w/2,-20,speed); //本来想文字在0,-20,但是这样的话文字站了从头到尾巴占了(0~w,20)




       painter.restore();

}

void Widget::drawIndicator(QPainter &painter)
{
    painter.save();
    //绘制指针

    double curAngle = m_startAngle + m_curSpeed * m_anglePerVel;
    painter.rotate(curAngle); //旋转坐标系

    QRadialGradient haloGradient(0, 0, 60, 0, 0);  //辐射渐变
    haloGradient.setColorAt(0, QColor(60,60,60));
    haloGradient.setColorAt(1, QColor(160,160,160)); //灰
    painter.setPen(Qt::white); //定义线条文本颜色  设置线条的颜色
    painter.setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色

    static const QPointF points[3] = {
        QPointF(0.0, 4),
        QPointF(0.0, -4),
        QPointF(68.0, 0),
    };
    painter.drawPolygon(points,3); //绘制多边形
    painter.restore();

    painter.save();
    //绘制旋转中心
    QRadialGradient rg(0,0,10);
    rg.setColorAt(0.0,Qt::darkGray);
    rg.setColorAt(0.5,Qt::white);
    rg.setColorAt(1.0,Qt::darkGray);
    painter.setPen(Qt::NoPen);
    painter.setBrush(rg);
    painter.drawEllipse(QPoint(0,0),10,10);

    painter.restore();
}

void Widget::on_pushButton_clicked()
{


        update();
        if((m_curSpeed*50) == m_maxSpeed)
                 m_curSpeed=0;
        else {
            m_curSpeed++;
        }


}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#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 drawFrame(QPainter &painter);
    void drawNumberIndicator(QPainter &painter);
    void drawDividing(QPainter &painter);
    void drawNumberSpeed(QPainter &painter);
    void drawIndicator(QPainter &painter);
protected:
    void paintEvent(QPaintEvent *);
private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    QWidget *m_wgt_mileage;
    qreal m_radius;

    int m_minSpeed;
    int m_maxSpeed;
    int  m_refSize;

    int m_startAngle;
    int m_anglePerVel;

    int m_endAngle;
    int m_curSpeed;

};
#endif // WIDGET_H

main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

untitle.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值