前言
通过Qt做一个UI界面显示飞控仪表数据情况,实时显示当前滚转角及俯仰角数据,并且绘制出仪表盘。本项目参考此篇博客https://blog.csdn.net/goldenhawking/article/details/78817426
效果
实验效果如下图所示,姿态仪显示当前的滚转角及俯仰角的数据(根据系统时间换算的随机数据),并根据其数据绘制仪表盘。
资源下载
本次实验全部代码请至https://download.csdn.net/download/wang_chao118/86458565下载。
核心代码
本项目工程文件夹目录如下图所示
定义了一个派生于QGraphicsView的Adi类,封装姿态仪所需相关属性及方法;LayoutSquare类派生于QLayout类,用于实现保持图片的纵横比例;WidgetADI类作为显示Adi的载体,封装了设置Adi类中各个变量的方法;Widget类为整体的底层显示界面。
Adi.hpp
#ifndef __qfi_Adi_H__
#define __qfi_Adi_H__
#include <QGraphicsView>
class QWidget;
class QResizeEvent;
class QGraphicsScene;
class QGraphicsSvgItem;
namespace qfi {
//---------------------------------------------------
// Class: Adi
// Description: Attitude Director Indicator
//---------------------------------------------------
class Adi : public QGraphicsView
{
Q_OBJECT
public:
Adi(QWidget* parent = nullptr);
virtual ~Adi();
// reinitiates widget
void reinit();
// refreshes (redraws) widget
void update();
void setRoll(const float);
void setPitch(const float);
protected:
void resizeEvent(QResizeEvent*);
private:
void init();
void reset();
void updateView();
QGraphicsScene* m_scene{};
QGraphicsSvgItem* m_itemBack{};
QGraphicsSvgItem* m_itemFace{};
QGraphicsSvgItem* m_itemRing{};
QGraphicsSvgItem* m_itemCase{};
float m_roll{};
float m_pitch{};
float m_faceDeltaX_new{};
float m_faceDeltaX_old{};
float m_faceDeltaY_new{};
float m_faceDeltaY_old{};
float m_scaleX{1.0f};
float m_scaleY{1.0f};
const int m_originalHeight{240};
const int m_originalWidth{240};
const float m_originalPixPerDeg{1.7f};
QPointF m_originalAdiCtr{120.0f, 120.0f};
const int m_backZ{-30};
const int m_faceZ{-20};
const int m_ringZ{-10};
const int m_caseZ{10};
};
}
#endif
#endif // HEROPLANE_H
Adi.cpp
#include "Adi.hpp"
#include <QGraphicsSvgItem>
#include <cmath>
#define M_PI 3.14159265358979323846 // pi
namespace qfi {
Adi::Adi(QWidget* parent) : QGraphicsView (parent)
{
m_scene = new QGraphicsScene( this );
setScene( m_scene );
m_scene->clear();
init();
}
Adi::~Adi()
{
if (m_scene) {
m_scene->clear();
delete m_scene;
m_scene = nullptr;
}
reset();
}
void Adi::reinit()
{
if (m_scene) {
m_scene->clear();
init();
}
}
void Adi::update()
{
updateView();
m_faceDeltaX_old = m_faceDeltaX_new;
m_faceDeltaY_old = m_faceDeltaY_new;
}
void Adi::setRoll(const float roll)
{
m_roll = roll;
if ( m_roll < -180.0f ) m_roll = -180.0f;
if ( m_roll > 180.0f ) m_roll = 180.0f;
}
void Adi::setPitch(const float pitch)
{
m_pitch = pitch;
if ( m_pitch < -25.0f ) m_pitch = -25.0f;
if ( m_pitch > 25.0f ) m_pitch = 25.0f;
}
void Adi::resizeEvent(QResizeEvent* event)
{
QGraphicsView::resizeEvent( event );
reinit();
}
void Adi::init()
{
m_scaleX = static_cast<float>(width()) / static_cast<float>(m_originalWidth);
m_scaleY = static_cast<float>(height()) / static_cast<float>(m_originalHeight);
reset();
m_itemBack = new QGraphicsSvgItem( ":/qfi/images/adi/adi_back.svg" );
m_itemBack->setCacheMode( QGraphicsItem::NoCache );
m_itemBack->setZValue( m_backZ );
m_itemBack->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemBack->setTransformOriginPoint( m_originalAdiCtr );
m_scene->addItem( m_itemBack );
m_itemFace = new QGraphicsSvgItem( ":/qfi/images/adi/adi_face.svg" );
m_itemFace->setCacheMode( QGraphicsItem::NoCache );
m_itemFace->setZValue( m_faceZ );
m_itemFace->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemFace->setTransformOriginPoint( m_originalAdiCtr );
m_scene->addItem( m_itemFace );
m_itemRing = new QGraphicsSvgItem( ":/qfi/images/adi/adi_ring.svg" );
m_itemRing->setCacheMode( QGraphicsItem::NoCache );
m_itemRing->setZValue( m_ringZ );
m_itemRing->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemRing->setTransformOriginPoint( m_originalAdiCtr );
m_scene->addItem( m_itemRing );
m_itemCase = new QGraphicsSvgItem( ":/qfi/images/adi/adi_case.svg" );
m_itemCase->setCacheMode( QGraphicsItem::NoCache );
m_itemCase->setZValue( m_caseZ );
m_itemCase->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_scene->addItem( m_itemCase );
centerOn( width() / 2.0f , height() / 2.0f );
updateView();
}
void Adi::reset()
{
m_itemBack = nullptr;
m_itemFace = nullptr;
m_itemRing = nullptr;
m_itemCase = nullptr;
m_roll = 0.0f;
m_pitch = 0.0f;
m_faceDeltaX_new = 0.0f;
m_faceDeltaX_old = 0.0f;
m_faceDeltaY_new = 0.0f;
m_faceDeltaY_old = 0.0f;
}
void Adi::updateView()
{
m_scaleX = static_cast<float>(width()) / static_cast<float>(m_originalWidth);
m_scaleY = static_cast<float>(height()) / static_cast<float>(m_originalHeight);
m_itemBack->setRotation(-m_roll);
m_itemFace->setRotation(-m_roll);
m_itemRing->setRotation(-m_roll);
const float roll_rad{static_cast<float>(M_PI * m_roll / 180.0)};
const float delta{static_cast<float>(m_originalPixPerDeg * m_pitch)};
m_faceDeltaX_new = m_scaleX * delta * std::sin( roll_rad );
m_faceDeltaY_new = m_scaleY * delta * std::cos( roll_rad );
m_itemFace->moveBy( m_faceDeltaX_new - m_faceDeltaX_old, m_faceDeltaY_new - m_faceDeltaY_old );
m_scene->update();
}
}
整体工程文件夹内内容见资源下载
资源下载
本次实验全部代码请至https://download.csdn.net/download/wang_chao118/86458565下载。