• Qt自定义控件之仪表盘3--雷达扫描图


    1、设计思想

    雷达扫描图,在影视作品中见到较多,比如飞机雷达、舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置。和汽车仪表盘类似,汽车仪表盘有底盘背景图、同圆、刻度、刻度值、旋转的指针。能在汽车仪表盘的基础上略作修改,比如指针换成带有余辉的扫描扇面,就能完成一个雷达扫描图。

    代码实现原理:
    上图的扫描线和余辉效果,可以使用QConicalGradient 函数来实现,qconicalgradient()提供的是一种扇形渐变效果,圆锥式渐变或称角度渐变。用这个渐变色来填充drawPie函数就可以实现扇形选择的余辉。

    QConicalGradient::QConicalGradient(qreal cx, qreal cy, qreal angle)

    void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)

    Qt大神刘典武文章中有典型的讲解,《Qt编写自定义控件62-探探雷达》中实现的扫描效果就是雷达的效果。详情移步https://zhuanlan.zhihu.com/p/85512788

     

    2、代码实现

    绘制同心圆,xy轴实线,45度对角线虚线。

    void Radar::drawCircle(QPainter *painter)
    {
        painter->save();
    
        QColor color = QColor(0, 100, 0);
        QPen pen = QPen(color, 2);
        painter->setPen(pen);
    
       for(int i=0; i<4; i++)
       {
           int r =  this->radius / 4 * (i+1);
           painter->drawEllipse(-r, -r, r * 2, r * 2);
       }
    
       for(int i=0; i<=4; i++) // x,y 轴线是实线
       {
           int r = this->radius;
           if((i%2) == 0) {
               pen.setStyle(Qt::SolidLine);
           }
           else{
               pen.setStyle(Qt::DashDotLine);
               //pen.setDashPattern(QVector<qreal>() << 10 << 2 ); //实线:空线的比例
           }
           painter->setPen(pen);
           painter->drawLine(-r, 0, r, 0);
           painter->rotate(90/2);
       }
    
        painter->restore();
    }

    绘制扫描图,依靠锥形渐变颜色,通过透明度控制形成扫描效果,然后绘制饼图。

    void Radar::drawScan(QPainter *painter)
    {
        painter->save();
    
        //锥形渐变颜色,通过透明度控制形成扫描效果
        QConicalGradient conicalGradient(0, 0, this->angle);
        QColor color = QColor(0,150,0);
        color.setAlpha(100);
        conicalGradient.setColorAt(0, color);
        color.setAlpha(20);
        conicalGradient.setColorAt(0.1, color);
        color.setAlpha(0);
        conicalGradient.setColorAt(1, color);
    
        //绘制饼圆
        QPen pen;
        pen.setWidth(5);
        pen.setBrush(conicalGradient);
        painter->setPen(pen);
        painter->setBrush(conicalGradient);
        int r =  this->radius;
        QRect rect(-r, -r, r * 2, r * 2);
        painter->drawPie(rect, this->angle * 16, 360 * 16); // 1/16th of a degree
    
        painter->restore();
    }

    给雷达加上模拟的扫描目标,实现起来很简单,就是打点。

    void Radar::drawPoints(QPainter *painter)
    {
        painter->save();
    
        QColor color = QColor(200, 10, 0);
        QPen pen = QPen(color, 1);
        painter->setPen(pen);
        painter->setBrush(color);
        for(int i=0; i<this->points.count(); i++)
        {
            int r =  6;
            QRect rect(points[i].x() - r/2, points[i].y() - r/2, r * 2, r * 2);
            painter->drawEllipse(rect);// 画实心小点
        }
    
        painter->restore();
    }

    最终效果如下。

    外层怎么 调用?使用信号和槽驱动Radar类对象。

    RadarScan::RadarScan(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::RadarScan)
    {
        ui->setupUi(this);
    
        // start and stop
        connect(this, &RadarScan::radar_state_changed,
                ui->radar, &Radar::radar_start_control);
    
        connect(ui->startButton, &QPushButton::clicked, [=](){
            emit radar_state_changed(true);
        });
    
        connect(ui->stopButton, &QPushButton::clicked, [=](){
            emit radar_state_changed(false);
        });
    
        // speed control
        connect(this, &RadarScan::radar_speed_changed,
                ui->radar, &Radar::radar_speed_control);
    
        connect(ui->fastButton, &QPushButton::clicked, [=](){
            emit radar_speed_changed(true);
        });
    
        connect(ui->slowButton, &QPushButton::clicked, [=](){
            emit radar_speed_changed(false);
        });
    
        connect(ui->randomButton, &QPushButton::clicked, ui->radar, &Radar::radar_random_point);
    }

    3、效果演示

     

    尊重技术文章,转载请注明!

    Qt自定义控件之仪表盘3--雷达扫描图

    https://www.cnblogs.com/pingwen/p/13426304.html

  • 相关阅读:
    SCAU 12新生赛 H 拥挤的华农校巴
    C#实现让CPU占用率曲线听你的指挥 可指定运行核心
    追MM与设计模式的有趣见解
    FTP操作类
    怎么知道页面被放大缩小了
    SerialPort同步和异步数据读取
    Java Web 应用程序转换为 ASP.NET
    ASP.NET中进行消息处理(MSMQ)
    解压缩文件类
    怎样成为优秀的软件模型设计者?
  • 原文地址:https://www.cnblogs.com/pingwen/p/13426304.html
Copyright © 2020-2023  润新知