仿 遥控器 摇杆控件

1,项目中 需要对遥控器的 控制进行PC端展示,因此 自己封装了一个 widget。用于摇杆数值的实时展示,效果如下

仿 遥控器 摇杆控件


2,思路

利用  paintEvent(QPaintEvent *)   事件,进行实时绘制,具体实现 如下

头文件

#ifndef JOYSTICK_H
#define JOYSTICK_H
#include <QWidget>
#include "pvgauge_global.h"

class GAUGE_EXPORT Joystick: public QWidget
{
    Q_OBJECT
public:
    explicit Joystick(QWidget *parent = nullptr);
    ~Joystick();

    /**
     * @brief 设置遥控器 量程,默认1000
     * @param range
     */
    void setRange(int range);

    /**
     * @brief 设置垂直位置
     * @param vValue
     */
    void setVValue(int vValue);

    /**
     * @brief 设置水平位置
     * @param hValue
     */
    void setHValue(int hValue);

protected:
    void paintEvent(QPaintEvent *);
    void resizeEvent(QResizeEvent *);
    void drawCircle(QPainter *painter);
    void drawHVLine(QPainter *painter);
    void drawHVPoint(QPainter *painter);

private:
    int m_radius;
    int m_centerX;
    int m_centerY;

    int m_range;  //遥控器量程
    int m_hValue;
    int m_vValue;

    int m_circleOffset;
    int m_pointOffset;

private:
    void initData();

};
#endif // JOYSTICK_H

 源文件

#include "joystick.h"
#include <QPainter>
#include <QDebug>

Joystick::Joystick(QWidget *parent):QWidget(parent),m_range(1000)
  ,m_hValue(500),m_vValue(-500)
{
    initData();
}

Joystick::~Joystick()
{

}

void Joystick::resizeEvent(QResizeEvent *)
{
    initData();
    update();
}

void Joystick::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width() / 2, height() / 2);	/* 坐标变换为窗体中心 */

    drawCircle(&painter);//圆
    drawHVLine(&painter);//水平 垂直线
    drawHVPoint(&painter);//线上 
}

void Joystick::drawCircle(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    /* 外边框 */
    int tempRadius=m_radius;
    QLinearGradient lg1(0, -tempRadius, 0, tempRadius);
    //lg1.setColorAt(0, QColor(255, 255, 255));
    //lg1.setColorAt(1, QColor(166, 166, 166));
    lg1.setColorAt(0, QColor(111, 111,111));
    lg1.setColorAt(1, QColor(111, 111, 111));
    painter->setBrush(lg1);
    painter->drawEllipse(-tempRadius, -tempRadius, tempRadius << 1, tempRadius << 1);

    /* 内边框 */
    tempRadius -= m_circleOffset;
    QLinearGradient lg2(0, -tempRadius, 0, tempRadius);
    // lg2.setColorAt(0, QColor(166, 166, 166));
    // lg2.setColorAt(1, QColor(255, 255, 255));

    lg2.setColorAt(0, QColor(255, 255, 255));
    lg2.setColorAt(1, QColor(255, 255, 255));
    painter->setBrush(lg2);
    painter->drawEllipse(-tempRadius, -tempRadius, tempRadius << 1, tempRadius << 1);

    /* 内部指示颜色 */
    tempRadius -= 4;
    QRadialGradient rg(0, 0, tempRadius);
    //    rg.setColorAt(0, QColor(0, 245, 0));
    //    rg.setColorAt(0.6, QColor(0, 210, 0));
    //    rg.setColorAt(1, QColor(0, 166, 0));
    rg.setColorAt(0, QColor(0, 0, 0,50));
    rg.setColorAt(1, QColor(0, 0, 0,50));

    painter->setBrush(rg);
    painter->drawEllipse(-tempRadius, -tempRadius, tempRadius << 1, tempRadius << 1);

    painter->restore();
}

void Joystick::drawHVLine(QPainter *painter)
{
    painter->save();
    painter->setPen(QColor(100,0,0));
    painter->setPen(Qt::DashLine);

    int hlineStartX = m_centerX-m_radius+m_circleOffset;
    int hlineStartY = m_centerY;
    int hlineStopX= m_centerX+m_radius-m_circleOffset;
    int hlineStopY= m_centerY;
    painter->drawLine(QPoint(hlineStartX+m_circleOffset+m_pointOffset,hlineStartY),QPoint(hlineStopX-m_circleOffset-m_pointOffset,hlineStopY));

    int vlineStartX = m_centerX ;
    int vlineStartY = m_centerY-m_radius+m_circleOffset;
    int vlineStopX=m_centerX;
    int vlineStopY=m_centerY+m_radius-m_circleOffset;
    painter->drawLine(QPoint(vlineStartX,vlineStartY+m_circleOffset+m_pointOffset),QPoint(vlineStopX,vlineStopY-m_circleOffset-m_pointOffset));

    painter->restore();
}

void Joystick::drawHVPoint(QPainter *painter)
{
    painter->save();
    int circleRadius=m_pointOffset*2;//圆点半径

    QBrush brush(QColor(0,255,255));
    painter->setBrush(brush);
    //水平点
    int hx=(m_hValue*(m_radius-m_circleOffset*2))/m_range;
    painter->drawEllipse(QPoint(hx,m_centerY),circleRadius,circleRadius);

    QBrush brush2(QColor(0,255,64));
    painter->setBrush(brush2);
    //垂直点
    int vY=(m_vValue*(m_radius-m_circleOffset*2))/m_range;
    painter->drawEllipse(QPoint(m_centerX,vY),circleRadius,circleRadius);

    painter->setPen(QColor(0,0,0));
    //水平文字
    painter->drawText(QPoint(hx-circleRadius,m_centerY+circleRadius*2+m_pointOffset),QString::number(m_hValue));
    //垂直文字
    painter->drawText(QPoint(m_centerX+circleRadius+m_pointOffset,vY+m_pointOffset),QString::number(-m_vValue));
    painter->restore();
}

void Joystick::setHValue(int hValue)
{
    m_hValue = hValue;
    update();
}

void Joystick::setVValue(int vValue)
{
    m_vValue = -vValue;
    update();
}

void Joystick::setRange(int range)
{
    m_range = range;
}

void Joystick::initData()
{
    m_radius = qMin(width()/2, height()/2);//半径
    //圆心
    m_centerX = 0;
    m_centerY = 0;

    m_circleOffset= m_radius/20+2;// 13;//内外圆 之差
    m_pointOffset=m_radius/50+2;// 5;//点 与文字的偏移
}