Qt绘制指南针(仪表盘绘制封装使用)

news2024/9/24 9:28:11

        指南针是一种用来确定方向的工具。它由一个磁针制成,其一端被磁化,可以自由旋转。当放置在水平面上时,磁针会指向地球的磁北极。通过观察磁针的指向,我们可以确定地理北方的方向。本示例是在Qt中绘制一个指南针,通过继承QWidget类,并重写其paintEvent函数来实现。并对仪表盘绘制进行封装。

一、简述

         这个示例创建了一个名为CompassWidget的自定义小部件,它继承自QWidget类。在paintEvent()函数中,我们使用QPainter类进行绘图操作。

二、 设计思路    
  1. 创建一个QWidget子类CompassWidget用于绘制指南针。
  2. 在CompassWidget的构造函数中,设置指南针的背景色、大小等属性。
  3. 定义QcGaugeWidget类,绘制指南针的各个组成部分,重写相关部件的paintEvent()函数。
  4. 使用QPainter在paintEvent()函数中绘制指南针的主体部分,包括圆形背景、指针和刻度。
  5. 根据指南针的当前角度,计算并绘制指针的位置和角度。
  6. 添加一个public的setCurrentValue()函数,用于设置指南针的角度,并在其中调用update()函数刷新界面。
三、效果 

 

四、核心代码  
1、头文件

        compasswidget.h 指南针表盘控件

#ifndef COMPASSWIDGET_H
#define COMPASSWIDGET_H

#include <QWidget>

class QcGaugeWidget;
class QcNeedleItem;
class QVBoxLayout;

class CompassWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CompassWidget(QWidget *parent = 0);
    ~CompassWidget();

public slots:
    void setCurrentValue(int value);

private:
    void init();

private:
    QcGaugeWidget   *m_pCompassGauge; //表盘
    QcNeedleItem    *m_pCompassNeedle; //指针
    QVBoxLayout     *m_pMainLayout;
};

#endif // COMPASSWIDGET_H

qcgaugewidget.h 仪表盘绘制封装(此处只有绘制指南针所需代码,全部代码请下载) 

#ifndef QCGAUGEWIDGET_H
#define QCGAUGEWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QObject>
#include <QRectF>
#include <QtMath>

class QcGaugeWidget;
class QcItem;
class QcBackgroundItem;
class QcDegreesItem;
class QcNeedleItem;
class QcLabelItem;
class QcGlassItem;

///
class QcGaugeWidget : public QWidget
{
    Q_OBJECT
public:
    explicit QcGaugeWidget(QWidget *parent = 0);    

    QcBackgroundItem* addBackground(float position);
    QcDegreesItem* addDegrees(float position);
    QcNeedleItem* addNeedle(float position);
    QcLabelItem* addLabel(float position);
    QcGlassItem* addGlass(float position);

    void addItem(QcItem* item, float position);
    int removeItem(QcItem* item);
    QList <QcItem*> items();
    QList <QcItem*> mItems;

private:
    void paintEvent(QPaintEvent *);

};

///
class QcItem : public QObject
{
    Q_OBJECT
public:
    explicit QcItem(QObject *parent = 0);
    virtual void draw(QPainter *) = 0;
    virtual int type();

    void setPosition(float percentage);
    float position();
    QRectF rect();
    enum Error{InvalidValueRange,InvalidDegreeRange,InvalidStep};

protected:
    QRectF adjustRect(float percentage);
    float getRadius(const QRectF &);
    float getAngle(const QPointF&, const QRectF &tmpRect);
    QPointF getPoint(float deg, const QRectF &tmpRect);
    QRectF resetRect();
    void update();

private:
    QRectF mRect;
    QWidget *parentWidget;
    float mPosition;
};

///
class QcScaleItem : public QcItem
{
    Q_OBJECT
public:
    explicit QcScaleItem(QObject *parent = 0);

    void setValueRange(float minValue,float maxValue);
    void setDgereeRange(float minDegree,float maxDegree);
    void setMinValue(float minValue);
    void setMaxValue(float maxValue);
    void setMinDegree(float minDegree);
    void setMaxDegree(float maxDegree);

protected:
    float getDegFromValue(float);

    float mMinValue;
    float mMaxValue;
    float mMinDegree;
    float mMaxDegree;
};

///
class QcBackgroundItem : public QcItem
{
    Q_OBJECT
public:
    explicit QcBackgroundItem(QObject *parent = 0);
    void draw(QPainter*);
    void addColor(float position, const QColor& color);
    void clearrColors();

private:
    QPen mPen;
    QList<QPair<float,QColor> > mColors;
    QLinearGradient mLinearGrad;
};

///
class QcGlassItem : public QcItem
{
    Q_OBJECT
public:
    explicit QcGlassItem(QObject *parent = 0);
    void draw(QPainter*);
};

///
class QcLabelItem : public QcItem
{
    Q_OBJECT
public:
    explicit QcLabelItem(QObject *parent = 0);
    virtual void draw(QPainter *);
    void setAngle(float);
    float angle();
    void setText(const QString &text, bool repaint = true);
    QString text();
    void setColor(const QColor& color);
    QColor color();

private:
    float mAngle;
    QString mText;
    QColor mColor;
};

///
class  QcDegreesItem : public QcScaleItem
{
    Q_OBJECT
public:
    explicit QcDegreesItem(QObject *parent = 0);
    void draw(QPainter *painter);
    void setStep(float step);
    void setColor(const QColor& color);
    void setSubDegree(bool );
private:
    float mStep;
    QColor mColor;
    bool mSubDegree;
};

///
class QcNeedleItem : public QcScaleItem
{
    Q_OBJECT
public:
    explicit QcNeedleItem(QObject *parent = 0);
    void draw(QPainter*);
    void setCurrentValue(float value);
    float currentValue();
    void setValueFormat(QString format);
    QString currentValueFormat();
    void setColor(const QColor & color);
    QColor color();

    void setLabel(QcLabelItem*);
    QcLabelItem * label();

    enum NeedleType{
        DiamonNeedle,
        TriangleNeedle,//三角指针
        FeatherNeedle,
        AttitudeMeterNeedle,
        CompassNeedle   //指南针
    };

    void setNeedle(QcNeedleItem::NeedleType needleType);
private:
    QPolygonF mNeedlePoly;
    float mCurrentValue;
    QColor mColor;
    void createDiamonNeedle(float r);
    void createTriangleNeedle(float r);
    void createFeatherNeedle(float r);
    void createAttitudeNeedle(float r);
    void createCompassNeedle(float r);
    NeedleType mNeedleType;
    QcLabelItem *mLabel;
    QString mFormat;
};

#endif // QCGAUGEWIDGET_H
2、实现代码

compasswidget.cpp 

#include "compasswidget.h"
#include <QVBoxLayout>
#include "qcgaugewidget.h"

CompassWidget::CompassWidget(QWidget *parent)
    : QWidget(parent)
{
    init();
}

CompassWidget::~CompassWidget()
{
}

void CompassWidget::setCurrentValue(int value)
{
    m_pCompassNeedle->setCurrentValue(value);
}

void CompassWidget::init()
{
    m_pCompassGauge = new QcGaugeWidget;

    m_pCompassGauge->addBackground(99);
    QcBackgroundItem *bkg1 = m_pCompassGauge->addBackground(92);
    bkg1->clearrColors();
    bkg1->addColor(0.1,Qt::black);
    bkg1->addColor(1.0,Qt::white);

    QcBackgroundItem *bkg2 = m_pCompassGauge->addBackground(88);
    bkg2->clearrColors();
    bkg2->addColor(0.1,Qt::white);
    bkg2->addColor(1.0,Qt::black);

    QcLabelItem *w = m_pCompassGauge->addLabel(80);//标签
    w->setText("W");
    w->setAngle(0);
    w->setColor(Qt::white);

    QcLabelItem *n = m_pCompassGauge->addLabel(80);
    n->setText("N");
    n->setAngle(90);
    n->setColor(Qt::white);

    QcLabelItem *e = m_pCompassGauge->addLabel(80);
    e->setText("E");
    e->setAngle(180);
    e->setColor(Qt::white);

    QcLabelItem *s = m_pCompassGauge->addLabel(80);
    s->setText("S");
    s->setAngle(270);
    s->setColor(Qt::white);

    QcDegreesItem *deg = m_pCompassGauge->addDegrees(70);//刻度
    deg->setStep(5);
    deg->setMaxDegree(270);
    deg->setMinDegree(-75);
    deg->setColor(Qt::white);
    m_pCompassNeedle = m_pCompassGauge->addNeedle(60);//指针
    m_pCompassNeedle->setNeedle(QcNeedleItem::CompassNeedle);
    m_pCompassNeedle->setValueRange(0,360);
    m_pCompassNeedle->setMaxDegree(360);
    m_pCompassNeedle->setMinDegree(0);
    m_pCompassGauge->addBackground(7);
    m_pCompassGauge->addGlass(88);//毛玻璃

    m_pMainLayout = new QVBoxLayout(this);
    m_pMainLayout->addWidget(m_pCompassGauge);
}

qcgaugewidget.cpp  仪表盘绘制封装(此处只有绘制指南针所需代码,全部代码请下载) 

#include "qcgaugewidget.h"

QcGaugeWidget::QcGaugeWidget(QWidget *parent) :
    QWidget(parent)
{
    setMinimumSize(250,250);
}

QcBackgroundItem *QcGaugeWidget::addBackground(float position)
{
    QcBackgroundItem * item = new QcBackgroundItem(this);
    item->setPosition(position);
    mItems.append(item);
    return item;
}

QcDegreesItem *QcGaugeWidget::addDegrees(float position)
{
    QcDegreesItem * item = new QcDegreesItem(this);
    item->setPosition(position);

    mItems.append(item);
    return item;
}

QcNeedleItem *QcGaugeWidget::addNeedle(float position)
{
    QcNeedleItem * item = new QcNeedleItem(this);
    item->setPosition(position);
    mItems.append(item);
    return item;
}

QcLabelItem *QcGaugeWidget::addLabel(float position)
{
    QcLabelItem * item = new QcLabelItem(this);
    item->setPosition(position);
    mItems.append(item);
    return item;
}

QcGlassItem *QcGaugeWidget::addGlass(float position)
{
    QcGlassItem * item = new QcGlassItem(this);
    item->setPosition(position);
    mItems.append(item);
    return item;
}

void QcGaugeWidget::addItem(QcItem *item,float position)
{
    item->setParent(this);
    item->setPosition(position);
    mItems.append(item);
}

int QcGaugeWidget::removeItem(QcItem *item)
{
   return mItems.removeAll(item);
}

QList<QcItem *> QcGaugeWidget::items()
{
    return mItems;
}


void QcGaugeWidget::paintEvent(QPaintEvent */*paintEvt*/)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    foreach (QcItem * item, mItems) {
        item->draw(&painter);
    }
}

///
QcItem::QcItem(QObject *parent) :
    QObject(parent)
{

    parentWidget = qobject_cast<QWidget*>(parent);
    mPosition = 50;
}

int QcItem::type()
{
    return 50;
}

void QcItem::update()
{
    parentWidget->update();
}

float QcItem::position()
{
    return mPosition;
}

QRectF QcItem::rect()
{
    return mRect;
}

void QcItem::setPosition(float position)
{
    if(position>100)
        mPosition = 100;
    else if(position<0)
        mPosition = 0;
    else
        mPosition = position;
    update();
}

QRectF QcItem::adjustRect(float percentage)
{
    float r = getRadius(mRect);
    float offset =   r-(percentage*r)/100.0;
    QRectF tmpRect = mRect.adjusted(offset,offset,-offset,-offset);
    return tmpRect;
}

float QcItem::getRadius(const QRectF &tmpRect)
{
    float r = 0;
    if(tmpRect.width()<tmpRect.height())
        r = tmpRect.width()/2.0;
    else
        r = tmpRect.height()/2.0;
    return r;
}

QRectF QcItem::resetRect()
{
    mRect = parentWidget->rect();
    float r = getRadius(mRect);
    mRect.setWidth(2.0*r);
    mRect.setHeight(2.0*r);
    mRect.moveCenter(parentWidget->rect().center());
    return mRect;
}

QPointF QcItem::getPoint(float deg,const QRectF &tmpRect)
{
    float r = getRadius(tmpRect);
    float xx=cos(qDegreesToRadians(deg))*r;
    float yy=sin(qDegreesToRadians(deg))*r;
    QPointF pt;
    xx=tmpRect.center().x()-xx;
    yy=tmpRect.center().y()-yy;
    pt.setX(xx);
    pt.setY(yy);
    return pt;
}

float QcItem::getAngle(const QPointF&pt, const QRectF &tmpRect)
{
    float xx=tmpRect.center().x()-pt.x();
    float yy=tmpRect.center().y()-pt.y();
    return qRadiansToDegrees( atan2(yy,xx));
}

///
QcScaleItem::QcScaleItem(QObject *parent) :
    QcItem(parent)
{
    mMinDegree = -45;
    mMaxDegree = 225;
    mMinValue = 0;
    mMaxValue = 100;
}

void QcScaleItem::setValueRange(float minValue, float maxValue)
{
    if(!(minValue<maxValue))
        throw( InvalidValueRange);
    mMinValue = minValue;
    mMaxValue = maxValue;

}

void QcScaleItem::setDgereeRange(float minDegree, float maxDegree)
{
    if(!(minDegree<maxDegree))
        throw( InvalidValueRange);
    mMinDegree = minDegree;
    mMaxDegree = maxDegree;
}

float QcScaleItem::getDegFromValue(float v)
{
    float a = (mMaxDegree-mMinDegree)/(mMaxValue-mMinValue);
    float b = -a*mMinValue+mMinDegree;
    return a*v+b;
}


void QcScaleItem::setMinValue(float minValue)
{
    if(minValue>mMaxValue)
        throw (InvalidValueRange);
    mMinValue = minValue;
    update();
}


void QcScaleItem::setMaxValue(float maxValue)
{
    if(maxValue<mMinValue )
        throw (InvalidValueRange);
    mMaxValue = maxValue;
    update();
}

void QcScaleItem::setMinDegree(float minDegree)
{
    if(minDegree>mMaxDegree)
        throw (InvalidDegreeRange);
    mMinDegree = minDegree;
    update();
}
void QcScaleItem::setMaxDegree(float maxDegree)
{
    if(maxDegree<mMinDegree)
        throw (InvalidDegreeRange);
    mMaxDegree = maxDegree;
    update();
}

///
QcBackgroundItem::QcBackgroundItem(QObject *parent) :
    QcItem(parent)
{
    setPosition(88);
    mPen = Qt::NoPen;
    setPosition(88);

    addColor(0.4,Qt::darkGray);
    addColor(0.8,Qt::black);

}

void QcBackgroundItem::draw(QPainter* painter)
{
    QRectF tmpRect = resetRect();
    painter->setBrush(Qt::NoBrush);
    QLinearGradient linearGrad(tmpRect.topLeft(), tmpRect.bottomRight());
    for(int i = 0;i<mColors.size();i++){
        linearGrad.setColorAt(mColors[i].first,mColors[i].second);
    }
    painter->setPen(mPen);
    painter->setBrush(linearGrad);
    painter->drawEllipse(adjustRect(position()));
}

void QcBackgroundItem::addColor(float position, const QColor &color)
{
    if(position<0||position>1)
        return;
      QPair<float,QColor> pair;
      pair.first = position;
      pair.second = color;
      mColors.append(pair);
      update();
}

void QcBackgroundItem::clearrColors()
{
    mColors.clear();
}

///
QcGlassItem::QcGlassItem(QObject *parent) :
    QcItem(parent)
{
    setPosition(88);
}

void QcGlassItem::draw(QPainter *painter)
{
    resetRect();
    QRectF tmpRect1 = adjustRect(position());
    QRectF tmpRect2 = tmpRect1;
    float r = getRadius(tmpRect1);
    tmpRect2.setHeight(r/2.0);
    painter->setPen(Qt::NoPen);

    QColor clr1 = Qt::gray ;
    QColor clr2 = Qt::white;
    clr1.setAlphaF(0.2);
    clr2.setAlphaF(0.4);

    QLinearGradient linearGrad1(tmpRect1.topLeft(), tmpRect1.bottomRight());
    linearGrad1.setColorAt(0.1, clr1);
    linearGrad1.setColorAt(0.5, clr2);

    painter->setBrush(linearGrad1);
    painter->drawPie(tmpRect1,0,16*180);
    tmpRect2.moveCenter(rect().center());
    painter->drawPie(tmpRect2,0,-16*180);
}

///
QcLabelItem::QcLabelItem(QObject *parent) :
    QcItem(parent)
{
    setPosition(50);
    mAngle = 270;
    mText = "%";
    mColor = Qt::black;
}

void QcLabelItem::draw(QPainter *painter)
{
    resetRect();
    QRectF tmpRect = adjustRect(position());
    float r = getRadius(rect());
    QFont font("Meiryo UI", r/10.0, QFont::Bold);
    painter->setFont(font);
    painter->setPen(QPen(mColor));

    QPointF txtCenter = getPoint(mAngle,tmpRect);
    QFontMetrics fMetrics = painter->fontMetrics();
    QSize sz = fMetrics.size( Qt::TextSingleLine, mText );
    QRectF txtRect(QPointF(0,0), sz );
    txtRect.moveCenter(txtCenter);

    painter->drawText( txtRect, Qt::TextSingleLine,mText );
}

void QcLabelItem::setAngle(float a)
{
    mAngle = a;
    update();
}

float QcLabelItem::angle()
{
    return mAngle;
}

void QcLabelItem::setText(const QString &text, bool repaint)
{
    mText = text;
    if(repaint)
        update();
}

QString QcLabelItem::text()
{
    return mText;
}

void QcLabelItem::setColor(const QColor &color)
{
    mColor = color;
    update();
}

QColor QcLabelItem::color()
{
    return mColor;
}

///
QcDegreesItem::QcDegreesItem(QObject *parent) :
    QcScaleItem(parent)
{
    mStep = 10;
    mColor = Qt::black;
    mSubDegree = false;
    setPosition(90);
}

void QcDegreesItem::draw(QPainter *painter)
{
    resetRect();
    QRectF tmpRect = adjustRect(position());

    painter->setPen(mColor);
    float r = getRadius(tmpRect);
    for(float val = mMinValue;val<=mMaxValue;val+=mStep){
        float deg = getDegFromValue(val);
        QPointF pt = getPoint(deg,tmpRect);
        QPainterPath path;
        path.moveTo(pt);
        path.lineTo(tmpRect.center());
        pt = path.pointAtPercent(0.03);
        QPointF newPt = path.pointAtPercent(0.13);

        QPen pen;
        pen.setColor(mColor);
        if(!mSubDegree)
            pen.setWidthF(r/25.0);

        painter->setPen(pen);
        painter->drawLine(pt,newPt);
    }
}

void QcDegreesItem::setStep(float step)
{
    mStep = step;
    update();
}

void QcDegreesItem::setColor(const QColor& color)
{
    mColor = color;
    update();
}

void QcDegreesItem::setSubDegree(bool b)
{
    mSubDegree = b;
    update();
}

///
QcNeedleItem::QcNeedleItem(QObject *parent) :
    QcScaleItem(parent)
{
    mCurrentValue = 0;
    mColor = Qt::black;
    mLabel = NULL;
    mNeedleType = FeatherNeedle;
}

void QcNeedleItem::draw(QPainter *painter)
{
    resetRect();
    QRectF tmpRect = adjustRect(position());
    painter->save();
    painter->translate(tmpRect.center());
    float deg = getDegFromValue( mCurrentValue);
    painter->rotate(deg+90.0);
    painter->setBrush(QBrush(mColor));
    painter->setPen(Qt::NoPen);

    QLinearGradient grad;

    switch (mNeedleType) {
    case QcNeedleItem::FeatherNeedle:
        createFeatherNeedle(getRadius(tmpRect));
        break;
    case QcNeedleItem::DiamonNeedle:
        createDiamonNeedle(getRadius(tmpRect));
        break;
    case QcNeedleItem::TriangleNeedle:
        createTriangleNeedle(getRadius(tmpRect));
        break;
    case QcNeedleItem::AttitudeMeterNeedle:
        createAttitudeNeedle(getRadius(tmpRect));
        break;
    case QcNeedleItem::CompassNeedle:
        createCompassNeedle(getRadius(tmpRect));
        grad.setStart(mNeedlePoly[0]);
        grad.setFinalStop(mNeedlePoly[1]);
        grad.setColorAt(0.9,Qt::red);
        grad.setColorAt(1,Qt::blue);
        painter->setBrush(grad);

        break;

    default:
        break;
    }
    painter->drawConvexPolygon(mNeedlePoly);
    painter->restore();
}

void QcNeedleItem::setCurrentValue(float value)
{
       if(value<mMinValue)
        mCurrentValue = mMinValue;
    else if(value>mMaxValue)
        mCurrentValue = mMaxValue;
    else
        mCurrentValue = value;

    if(mLabel!=0)
        mLabel->setText(QString::number(mCurrentValue),false);

    update();
}

float QcNeedleItem::currentValue()
{
    return mCurrentValue;
}

void QcNeedleItem::setValueFormat(QString format){
    mFormat = format;
    update();
}

QString QcNeedleItem::currentValueFormat(){
    return mFormat;
}

void QcNeedleItem::setColor(const QColor &color)
{
    mColor = color;
    update();
}

QColor QcNeedleItem::color()
{
    return mColor;
}

void QcNeedleItem::setLabel(QcLabelItem *label)
{
    mLabel = label;
    update();
}

QcLabelItem *QcNeedleItem::label()
{
    return mLabel;
}


void QcNeedleItem::setNeedle(QcNeedleItem::NeedleType needleType)
{
    mNeedleType = needleType;
    update();
}


void QcNeedleItem::createDiamonNeedle(float r)
{
    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0, 0.0));
    tmpPoints.append(QPointF(-r/20.0,r/20.0));
    tmpPoints.append(QPointF(0.0, r));
    tmpPoints.append(QPointF(r/20.0,r/20.0));
    mNeedlePoly = tmpPoints;
}

void QcNeedleItem::createTriangleNeedle(float r)
{
    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0, r));
    tmpPoints.append(QPointF(-r/40.0, 0.0));
    tmpPoints.append(QPointF(r/40.0,0.0));
    mNeedlePoly = tmpPoints;
}

void QcNeedleItem::createFeatherNeedle(float r)
{
    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0, r));
    tmpPoints.append(QPointF(-r/40.0, 0.0));
    tmpPoints.append(QPointF(-r/15.0, -r/5.0));
    tmpPoints.append(QPointF(r/15.0,-r/5));
    tmpPoints.append(QPointF(r/40.0,0.0));
    mNeedlePoly = tmpPoints;
}

void QcNeedleItem::createAttitudeNeedle(float r)
{
    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0, r));
    tmpPoints.append(QPointF(-r/20.0, 0.85*r));
    tmpPoints.append(QPointF(r/20.0,0.85*r));
    mNeedlePoly = tmpPoints;
}

void QcNeedleItem::createCompassNeedle(float r)
{
    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0, r));
    tmpPoints.append(QPointF(-r/15.0, 0.0));
    tmpPoints.append(QPointF(0.0, -r));
    tmpPoints.append(QPointF(r/15.0,0.0));
    mNeedlePoly = tmpPoints;
}

以上是Qt绘制指南针实现代码,在实际使用中,可以根据需要自定义动画文件和样式。

该自定义控件主要特点有:

1、纯QPaint绘制,不包括图片等文件;

2、多种自定义控制,非常灵活;

3、能够自适应大小,不需要手动调整;

        需要注意的是,在使用QPainter时,需要灵活运用QPainter的绘图函数和提供给用户的交互函数,并注意处理用户的交互操作和组件的尺寸调整等问题。

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include "compasswidget.h"
#include <QSlider>
#include <QHBoxLayout>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    CompassWidget *pCompassWidget = new CompassWidget(this);

    QSlider *slider = new QSlider(this);
    slider->setRange(0, 360);

    connect(slider, &QSlider::valueChanged, pCompassWidget, &CompassWidget::setCurrentValue);

    QWidget *widget = new QWidget(this);
    QHBoxLayout *layout = new QHBoxLayout(widget);
    layout->addWidget(pCompassWidget);
    layout->addWidget(slider);
    setCentralWidget(widget);

    resize(400, 400);
}

MainWindow::~MainWindow()
{
}

总结一下,指南针的设计方法和流程如下:

1、绘制指南针的背景。可以使用QPainter的drawEllipse方法来绘制一个圆形背景,然后填充颜色。

2、绘制指南针的刻度。可以使用QPainter的drawLine方法绘制指南针的刻度线,通过循环来绘制所有的刻度。

3、绘制指南针的指针。可以使用QPainter的drawLine方法绘制指南针的指针线,通过计算指针的角度来确定其位置。

4、绘制指南针的文字标签。可以使用QPainter的drawText方法绘制文字,并根据指南针的角度来确定文字标签的位置。

六、绘制一个速度表盘 

        我们利用QcGaugeWidget 将CompassWidget内init稍作修改即可实现一个速度仪表盘,代码如下(表盘和指针对象名称已修改):  

    m_pSpeedGauge = new QcGaugeWidget(this);
    m_pSpeedGauge->addBackground(99);
    QcBackgroundItem *bkg1 = m_pSpeedGauge->addBackground(92);
    bkg1->clearrColors();
    bkg1->addColor(0.1,Qt::black);
    bkg1->addColor(1.0,Qt::white);

    QcBackgroundItem *bkg2 = m_pSpeedGauge->addBackground(88);
    bkg2->clearrColors();
    bkg2->addColor(0.1,Qt::gray);
    bkg2->addColor(1.0,Qt::darkGray);

    m_pSpeedGauge->addArc(55);
    m_pSpeedGauge->addDegrees(65)->setValueRange(0,80);
    m_pSpeedGauge->addColorBand(50);

    m_pSpeedGauge->addValues(80)->setValueRange(0,80);

    m_pSpeedGauge->addLabel(70)->setText("Km/h");
    QcLabelItem *lab = m_pSpeedGauge->addLabel(40);
    lab->setText("0");
    m_pSpeedNeedle = m_pSpeedGauge->addNeedle(60);
    m_pSpeedNeedle->setLabel(lab);
    m_pSpeedNeedle->setColor(Qt::white);
    m_pSpeedNeedle->setValueRange(0,80);
    m_pSpeedGauge->addBackground(7);
    m_pSpeedGauge->addGlass(88);

    m_pMainLayout = new QVBoxLayout(this);
    m_pMainLayout->addWidget(m_pSpeedGauge);

    setLayout(m_pMainLayout);

效果如下:

 

        谢谢您的关注和阅读。如果您还有其他问题或需要进一步的帮助,请随时联系我。祝您一切顺利!

七、源代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot+vue+uniapp的宿舍管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

C++学习笔记02-结构基础(问题-解答自查版)

前言 以下问题以Q&A形式记录&#xff0c;基本上都是笔者在初学一轮后&#xff0c;掌握不牢或者频繁忘记的点 Q&A的形式有助于学习过程中时刻关注自己的输入与输出关系&#xff0c;也适合做查漏补缺和复盘。 本文对读者可以用作自查&#xff0c;答案在后面&#xff0…

Git的使用教程

仓库分区 Git本地有三个工作区域:工作目录&#xff08;Working Directory&#xff09;,暂存区&#xff08;Stage/Index&#xff09;&#xff0c;资源库&#xff08;Repository或Git Directory&#xff09;。如果再加上远程的git仓库&#xff08;Remove Directory&#xff09;就…

SAP PP 物料主数据字段状态控制

参考 https://zhuanlan.zhihu.com/p/452823415 物料主数据里面的状态 由 1、行业 2、工厂 3、物料类型 4、事务代码 5、采购相关字段 6、客制 优先级 隐藏->显示->必输->可选

Go基础编程 - 11 - 函数(func)

接口&#xff08;interface&#xff09; 函数1. 函数定义1.1. 函数名1.2. 参数列表1.3. 返回值列表 2. 匿名函数3. 闭包、递归3.1 闭包3.1.1 函数、引用环境3.1.2 闭包的延迟绑定3.1.3 goroutine 的延迟绑定 3.2 递归函数 4. 延迟调用&#xff08;defer&#xff09;4.1 defer特…

C语言中的控制语句(三):while 和 do while 语句

文章目录 [toc] &#x1f34a;自我介绍&#x1f34a;while语句&#x1f34a;do...while循环&#x1f34a;&#x1f34a; 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff09;哦~ &#x1f34a;自我介绍 Hello…

单调栈(随缘复习到了,顺手刷了)

也是不知道为什么突然又复习到单调栈了&#xff0c;所以顺手刷了三道题&#xff0c;总结一下 P6503 [COCI2010-2011#3] DIFERENCIJA 思路&#xff1a;这题是要求每个子区间里面的最大值和最小值的差&#xff0c;我们一开始想的必然是纯暴力呀&#xff0c;但是一看这数据&#…

主流硬派SUV齐聚尼三锅,方程豹豹5成功冲顶

随着汽车的飞速普及&#xff0c;越来越多的车主都喜欢上了越野。 而在浩瀚无垠的沙漠腹地&#xff0c;尼三锅以其独特的地理形态&#xff0c;成为了无数越野爱好者心中的圣地与试炼场。 近日&#xff0c;众多汽车博主携自己的爱车普拉多、方程豹豹5、牧马人、坦克400、坦克700、…

图书馆座位管理系统 /图书馆座位预约系统/图书馆管理系统的设计与实现

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

excel批量新建多个同类型的表格

背景引入 比如&#xff0c;一个企业有多个部门&#xff0c;现在需要按照某一个excel表模板收集各个部门的信息&#xff0c;需要创建数十个同类型表格&#xff0c;且标题要包含部门名称。 1.修改模板表格标题 在一个文件夹下面放入需要发放给各个部门的表格&#xff0c;将标题…

轨迹优化 | 基于ESDF的共轭梯度优化算法(附ROS C++/Python仿真)

目录 0 专栏介绍1 数值优化&#xff1a;共轭梯度法2 基于共轭梯度法的轨迹优化2.1 障碍约束函数2.2 曲率约束函数2.3 平滑约束函数 3 算法仿真3.1 ROS C实现3.2 Python实现 0 专栏介绍 &#x1f525;课程设计、毕业设计、创新竞赛、学术研究必备&#xff01;本专栏涉及更高阶的…

Chapter17 表面着色器——Shader入门精要学习

Chapter17 表面着色器 一、编译指令1.表面函数2.光照函数3.其他可选参数 二、两个结构体1.Input 结构体&#xff1a;数据来源2.SurfaceOutput 三、Unity背后做了什么四、表面着色器的缺点 一、编译指令 作用&#xff1a;指明该表面着色器的 表面函数 和 光照函数&#xff0c;并…

LeetCode 58.最后一个单词的长度 C++

LeetCode 58.最后一个单词的长度 C 思路&#x1f914;&#xff1a; 先解决当最后字符为空格的情况&#xff0c;如果最后字符为空格下标就往后移动&#xff0c;直到不为空格才停止&#xff0c;然后用rfind查询空格找到的就是最后一个单词的起始位置&#xff0c;最后相减就是单词…

前台文本直接取数据库值doFieldSQL插入SQL

实现功能&#xff1a;根据选择的车间主任带出角色。 实现步骤&#xff1a;OA的“字段联动”功能下拉选项带不出表“hrmrolemembers”&#xff0c;所以采用此方法。 doFieldSQL("select roleid from HrmResource as a inner join hrmrolemembers as b on a.id b.resource…

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 目录 AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 一、简单介绍 二、Transformer 1、模型架构 2、应用场景 3、Hugging …

Flink架构底层原理详解:案例解析(43天)

系列文章目录 一、Flink架构&#xff08;掌握&#xff09; 二、Flink代码案例&#xff08;掌握&#xff09; 三、UDF&#xff08;熟悉&#xff09; 四、Flink常见面试题整理 文章目录 系列文章目录前言一、Flink架构&#xff08;掌握&#xff09;1、系统架构1.1 通信&#xff…

海康威视工业相机SDK+Python+PyQt开发数据采集系统(支持软件触发、编码器触发)

海康威视工业相机SDKPythonPyQt开发数据采集系统&#xff08;支持软件触发、编码器触发&#xff09; pythonpyqt开发海康相机数据采集系统 1 开发软件功能&#xff1a; 支持搜索相机&#xff1a;Gige相机设备和USB相机设备支持两种触发模式&#xff1a;软件触发和编码器触发支…

Docker、containerd、CRI-O 和 runc 之间的区别

容器与 Docker 这个名称并不紧密相关。你可以使用其他工具来运行容器 您可以使用 Docker 或一堆非Docker 的其他工具来运行容器。docker只是众多选项之一&#xff0c;Docker&#xff08;公司&#xff09;在生态系统中创建了一些很棒的工具&#xff0c;但不是全部。 容器方面有…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十三章 驱动模块传参

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

【PPT把当前页输出为图片】及【PPT导出图片模糊】的解决方法(sci论文图片清晰度)

【PPT把当前页输出为图片】及【PPT导出图片模糊】的解决方法 内容一&#xff1a;ppt把当前页输出为图片&#xff1a;内容二&#xff1a;ppt导出图片模糊的解决方法&#xff1a;方法&#xff1a;步骤1&#xff1a;打开注册表编辑器步骤2&#xff1a;修改注册表&#xff1a; 该文…