WidgetNAV控件
经过(1)对航空仪表的了解及界面的介绍,(2)对WidgetPFD控件的介绍
本节继续了解下图控件的具体操作:
WidgetNAV.h
#ifndef WIDGETNAV_H
#define WIDGETNAV_H
#include <QWidget>
#include <qfi_NAV.h>
#include "LayoutSquare.h"
namespace Ui
{
class WidgetNAV;
}
class WidgetNAV : public QWidget
{
Q_OBJECT
public:
explicit WidgetNAV( QWidget *parent = 0 );
virtual ~WidgetNAV();
inline void update()
{
m_nav->update();
}
inline void setHeading( float heading )
{
m_nav->setHeading( heading );
}
inline void setHeadingBug( float headingBug )
{
m_nav->setHeadingBug( headingBug );
}
inline void setCourse( float course )
{
m_nav->setCourse( course );
}
inline void setBearing( float bearing, bool visible = false )
{
m_nav->setBearing( bearing, visible );
}
inline void setDeviation( float deviation, bool visible = false )
{
m_nav->setDeviation( deviation, visible );
}
inline void setDistance( float distance, bool visible = false )
{
m_nav->setDistance( distance, visible );
}
private:
Ui::WidgetNAV *m_ui;
qfi_NAV *m_nav;
LayoutSquare *m_layoutSq;
void setupUi();
};
#endif // WIDGETNAV_H
WidgetNAV.cpp
#ifndef WIDGETNAV_CPP
#define WIDGETNAV_CPP
#endif
#include "WidgetNAV.h"
#include "ui_WidgetNAV.h"
WidgetNAV::WidgetNAV( QWidget *parent ) :
QWidget( parent ),
m_ui( new Ui::WidgetNAV ),
m_nav ( 0 ),
m_layoutSq ( 0 )
{
m_ui->setupUi( this );
setupUi();
m_nav = m_ui->graphicsNAV;
}
WidgetNAV::~WidgetNAV()
{
if ( m_layoutSq ) delete m_layoutSq; m_layoutSq = 0;
if ( m_ui ) delete m_ui; m_ui = 0;
}
void WidgetNAV::setupUi()
{
m_layoutSq = new LayoutSquare( this );
m_layoutSq->setContentsMargins( 0, 0, 0, 0 );
m_layoutSq->addWidget( m_ui->frameNAV );
setLayout( m_layoutSq );
}
qfi_NAV.h
#ifndef QFI_NAV_H
#define QFI_NAV_H
#include <QGraphicsView>
#include <QGraphicsSvgItem>
/** This class provides Navigation Display widget. */
class qfi_NAV : public QGraphicsView
{
Q_OBJECT
public:
/** Constructor. */
explicit qfi_NAV( QWidget *parent = 0 );
/** Destructor. */
virtual ~qfi_NAV();
/** Reinitiates widget. */
void reinit();
/** Refreshes (redraws) widget. */
void update();
/** @param heading [deg] */
void setHeading( float heading );
/** @param heading bug [deg] */
void setHeadingBug( float headingBug );
/** @param course [deg] */
void setCourse( float course );
/** @param bearing [deg] */
void setBearing( float bearing, bool visible = false );
/** @param deviation [-] */
void setDeviation( float deviation, bool visible = false );
/** @param distance [nm] */
void setDistance( float distance, bool visible = false );
protected:
/** */
void resizeEvent( QResizeEvent *event );
private:
QGraphicsScene *m_scene; ///< graphics scene
QGraphicsSvgItem *m_itemBack; ///< NAV background
QGraphicsSvgItem *m_itemMask; ///< NAV mask
QGraphicsSvgItem *m_itemMark;
QGraphicsSvgItem *m_itemBrgArrow;
QGraphicsSvgItem *m_itemCrsArrow;
QGraphicsSvgItem *m_itemDevBar;
QGraphicsSvgItem *m_itemDevScale;
QGraphicsSvgItem *m_itemHdgBug;
QGraphicsSvgItem *m_itemHdgScale;
QGraphicsTextItem *m_itemCrsText;
QGraphicsTextItem *m_itemHdgText;
QGraphicsTextItem *m_itemDmeText;
QColor m_crsTextColor;
QColor m_hdgTextColor;
QColor m_dmeTextColor;
QFont m_crsTextFont;
QFont m_hdgTextFont;
QFont m_dmeTextFont;
float m_heading; ///< [deg]
float m_headingBug; ///< [deg]
float m_course;
float m_bearing;
float m_deviation;
float m_distance;
bool m_bearingVisible;
bool m_deviationVisible;
bool m_distanceVisible;
float m_devBarDeltaX_new;
float m_devBarDeltaX_old;
float m_devBarDeltaY_new;
float m_devBarDeltaY_old;
float m_scaleX; ///<
float m_scaleY; ///<
float m_originalPixPerDev;
QPointF m_originalNavCtr;
QPointF m_originalCrsTextCtr;
QPointF m_originalHdgTextCtr;
QPointF m_originalDmeTextCtr;
const int m_originalHeight; ///< [px]
const int m_originalWidth; ///< [px]
const int m_backZ;
const int m_maskZ;
const int m_markZ;
const int m_brgArrowZ;
const int m_crsArrowZ;
const int m_crsTextZ;
const int m_devBarZ;
const int m_devScaleZ;
const int m_hdgBugZ;
const int m_hdgScaleZ;
const int m_hdgTextZ;
const int m_dmeTextZ;
/** */
void init();
/** */
void reset();
/** */
void updateView();
};
#endif // QFI_NAV_H
qfi_NAV.cpp
#ifndef QFI_NAV_CPP
#define QFI_NAV_CPP
#endif
#include <iostream>
#ifdef WIN32
# include <float.h>
#endif
#include <math.h>
#include <stdio.h>
#include "qfi_NAV.h"
qfi_NAV::qfi_NAV( QWidget *parent ) :
QGraphicsView ( parent ),
m_scene ( 0 ),
m_itemBack ( 0 ),
m_itemMask ( 0 ),
m_itemMark ( 0 ),
m_itemBrgArrow ( 0 ),
m_itemCrsArrow ( 0 ),
m_itemDevBar ( 0 ),
m_itemDevScale ( 0 ),
m_itemHdgBug ( 0 ),
m_itemHdgScale ( 0 ),
m_itemCrsText ( 0 ),
m_itemHdgText ( 0 ),
m_itemDmeText ( 0 ),
m_crsTextColor ( 0, 255, 0 ),
m_hdgTextColor ( 255, 0, 255 ),
m_dmeTextColor ( 255, 255, 255 ),
m_heading ( 0.0f ),
m_headingBug ( 0.0f ),
m_course ( 0.0f ),
m_bearing ( 0.0f ),
m_deviation ( 0.0f ),
m_distance ( 0.0f ),
m_bearingVisible ( true ),
m_deviationVisible ( true ),
m_distanceVisible ( true ),
m_devBarDeltaX_new ( 0.0f ),
m_devBarDeltaX_old ( 0.0f ),
m_devBarDeltaY_new ( 0.0f ),
m_devBarDeltaY_old ( 0.0f ),
m_scaleX ( 1.0f ),
m_scaleY ( 1.0f ),
m_originalPixPerDev ( 52.5f ),
m_originalNavCtr ( 150.0f, 150.0f ),
m_originalCrsTextCtr ( 50.0f, 25.0f ),
m_originalHdgTextCtr ( 250.0f, 25.0f ),
m_originalDmeTextCtr ( 250.0f, 275.0f ),
m_originalHeight ( 300 ),
m_originalWidth ( 300 ),
m_backZ ( 0 ),
m_maskZ ( 100 ),
m_markZ ( 200 ),
m_brgArrowZ ( 60 ),
m_crsArrowZ ( 70 ),
m_crsTextZ ( 130 ),
m_devBarZ ( 50 ),
m_devScaleZ ( 10 ),
m_hdgBugZ ( 120 ),
m_hdgScaleZ ( 110 ),
m_hdgTextZ ( 130 ),
m_dmeTextZ ( 130 )
{
# ifdef WIN32
m_crsTextFont.setFamily( "Courier" );
m_crsTextFont.setPointSizeF( 12.0f );
m_crsTextFont.setStretch( QFont::Condensed );
m_crsTextFont.setWeight( QFont::Bold );
m_hdgTextFont.setFamily( "Courier" );
m_hdgTextFont.setPointSizeF( 12.0f );
m_hdgTextFont.setStretch( QFont::Condensed );
m_hdgTextFont.setWeight( QFont::Bold );
m_dmeTextFont.setFamily( "Courier" );
m_dmeTextFont.setPointSizeF( 10.0f );
m_dmeTextFont.setStretch( QFont::Condensed );
m_dmeTextFont.setWeight( QFont::Bold );
# else
m_crsTextFont.setFamily( "courier" );
m_crsTextFont.setPointSizeF( 12.0f );
m_crsTextFont.setStretch( QFont::Condensed );
m_crsTextFont.setWeight( QFont::Bold );
m_hdgTextFont.setFamily( "courier" );
m_hdgTextFont.setPointSizeF( 12.0f );
m_hdgTextFont.setStretch( QFont::Condensed );
m_hdgTextFont.setWeight( QFont::Bold );
m_dmeTextFont.setFamily( "courier" );
m_dmeTextFont.setPointSizeF( 10.0f );
m_dmeTextFont.setStretch( QFont::Condensed );
m_dmeTextFont.setWeight( QFont::Bold );
# endif
reset();
m_scene = new QGraphicsScene( this );
setScene( m_scene );
m_scene->clear();
init();
}
qfi_NAV::~qfi_NAV()
{
if ( m_scene )
{
m_scene->clear();
delete m_scene;
m_scene = 0;
}
reset();
}
void qfi_NAV::reinit()
{
if ( m_scene )
{
m_scene->clear();
init();
}
}
void qfi_NAV::update()
{
updateView();
m_devBarDeltaX_old = m_devBarDeltaX_new;
m_devBarDeltaY_old = m_devBarDeltaY_new;
}
void qfi_NAV::setHeading( float heading )
{
m_heading = heading;
while ( m_heading < 0.0f ) m_heading += 360.0f;
while ( m_heading > 360.0f ) m_heading -= 360.0f;
}
void qfi_NAV::setHeadingBug( float headingBug )
{
m_headingBug = headingBug;
while ( m_headingBug < 0.0f ) m_headingBug += 360.0f;
while ( m_headingBug > 360.0f ) m_headingBug -= 360.0f;
}
void qfi_NAV::setCourse( float course )
{
m_course = course;
while ( m_course < 0.0f ) m_course += 360.0f;
while ( m_course > 360.0f ) m_course -= 360.0f;
}
void qfi_NAV::setBearing( float bearing, bool visible )
{
m_bearing = bearing;
m_bearingVisible = visible;
while ( m_bearing < 0.0f ) m_bearing += 360.0f;
while ( m_bearing > 360.0f ) m_bearing -= 360.0f;
}
void qfi_NAV::setDeviation( float deviation, bool visible )
{
m_deviation = deviation;
m_deviationVisible = visible;
if ( m_deviation < -1.0f ) m_deviation = -1.0f;
if ( m_deviation > 1.0f ) m_deviation = 1.0f;
}
void qfi_NAV::setDistance( float distance, bool visible )
{
m_distance = fabs( distance );
m_distanceVisible = visible;
}
void qfi_NAV::resizeEvent( QResizeEvent *event )
{
QGraphicsView::resizeEvent( event );
reinit();
}
void qfi_NAV::init()
{
m_scaleX = (float)width() / (float)m_originalWidth;
m_scaleY = (float)height() / (float)m_originalHeight;
m_itemBack = new QGraphicsSvgItem( ":/qfi/images/nav/nav_back.svg" );
m_itemBack->setCacheMode( QGraphicsItem::NoCache );
m_itemBack->setZValue( m_backZ );
m_itemBack->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_scene->addItem( m_itemBack );
m_itemMask = new QGraphicsSvgItem( ":/qfi/images/nav/nav_mask.svg" );
m_itemMask->setCacheMode( QGraphicsItem::NoCache );
m_itemMask->setZValue( m_maskZ );
m_itemMask->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_scene->addItem( m_itemMask );
m_itemMark = new QGraphicsSvgItem( ":/qfi/images/nav/nav_mark.svg" );
m_itemMark->setCacheMode( QGraphicsItem::NoCache );
m_itemMark->setZValue( m_markZ );
m_itemMark->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_scene->addItem( m_itemMark );
m_itemBrgArrow = new QGraphicsSvgItem( ":/qfi/images/nav/nav_brg_arrow.svg" );
m_itemBrgArrow->setCacheMode( QGraphicsItem::NoCache );
m_itemBrgArrow->setZValue( m_brgArrowZ );
m_itemBrgArrow->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemBrgArrow->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemBrgArrow );
m_itemCrsArrow = new QGraphicsSvgItem( ":/qfi/images/nav/nav_crs_arrow.svg" );
m_itemCrsArrow->setCacheMode( QGraphicsItem::NoCache );
m_itemCrsArrow->setZValue( m_crsArrowZ );
m_itemCrsArrow->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemCrsArrow->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemCrsArrow );
m_itemDevBar = new QGraphicsSvgItem( ":/qfi/images/nav/nav_dev_bar.svg" );
m_itemDevBar->setCacheMode( QGraphicsItem::NoCache );
m_itemDevBar->setZValue( m_devBarZ );
m_itemDevBar->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemDevBar->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemDevBar );
m_itemDevScale = new QGraphicsSvgItem( ":/qfi/images/nav/nav_dev_scale.svg" );
m_itemDevScale->setCacheMode( QGraphicsItem::NoCache );
m_itemDevScale->setZValue( m_devScaleZ );
m_itemDevScale->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemDevScale->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemDevScale );
m_itemHdgBug = new QGraphicsSvgItem( ":/qfi/images/nav/nav_hdg_bug.svg" );
m_itemHdgBug->setCacheMode( QGraphicsItem::NoCache );
m_itemHdgBug->setZValue( m_hdgBugZ );
m_itemHdgBug->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemHdgBug->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemHdgBug );
m_itemHdgScale = new QGraphicsSvgItem( ":/qfi/images/nav/nav_hdg_scale.svg" );
m_itemHdgScale->setCacheMode( QGraphicsItem::NoCache );
m_itemHdgScale->setZValue( m_hdgScaleZ );
m_itemHdgScale->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemHdgScale->setTransformOriginPoint( m_originalNavCtr );
m_scene->addItem( m_itemHdgScale );
m_itemCrsText = 0;
m_itemCrsText = new QGraphicsTextItem( QString( "CRS 999" ) );
m_itemCrsText->setCacheMode( QGraphicsItem::NoCache );
m_itemCrsText->setZValue( m_crsTextZ );
m_itemCrsText->setDefaultTextColor( m_crsTextColor );
m_itemCrsText->setFont( m_crsTextFont );
m_itemCrsText->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemCrsText->moveBy( m_scaleX * ( m_originalCrsTextCtr.x() - m_itemCrsText->boundingRect().width() / 2.0f ),
m_scaleY * ( m_originalCrsTextCtr.y() - m_itemCrsText->boundingRect().height() / 2.0f ) );
m_scene->addItem( m_itemCrsText );
m_itemHdgText = new QGraphicsTextItem( QString( "HDG 999" ) );
m_itemHdgText->setCacheMode( QGraphicsItem::NoCache );
m_itemHdgText->setZValue( m_hdgTextZ );
m_itemHdgText->setDefaultTextColor( m_hdgTextColor );
m_itemHdgText->setFont( m_hdgTextFont );
m_itemHdgText->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemHdgText->moveBy( m_scaleX * ( m_originalHdgTextCtr.x() - m_itemHdgText->boundingRect().width() / 2.0f ),
m_scaleY * ( m_originalHdgTextCtr.y() - m_itemHdgText->boundingRect().height() / 2.0f ) );
m_scene->addItem( m_itemHdgText );
m_itemDmeText = new QGraphicsTextItem( QString( "99.9 NM" ) );
m_itemDmeText->setCacheMode( QGraphicsItem::NoCache );
m_itemDmeText->setZValue( m_dmeTextZ );
m_itemDmeText->setDefaultTextColor( m_dmeTextColor );
m_itemDmeText->setFont( m_dmeTextFont );
m_itemDmeText->setTransform( QTransform::fromScale( m_scaleX, m_scaleY ), true );
m_itemDmeText->moveBy( m_scaleX * ( m_originalDmeTextCtr.x() - m_itemDmeText->boundingRect().width() / 2.0f ),
m_scaleY * ( m_originalDmeTextCtr.y() - m_itemDmeText->boundingRect().height() / 2.0f ) );
m_scene->addItem( m_itemDmeText );
updateView();
}
void qfi_NAV::reset()
{
m_itemBrgArrow = 0;
m_itemCrsArrow = 0;
m_itemDevBar = 0;
m_itemDevScale = 0;
m_itemHdgBug = 0;
m_itemHdgScale = 0;
m_itemCrsText = 0;
m_itemHdgText = 0;
m_itemDmeText = 0;
m_heading = 0.0f;
m_headingBug = 0.0f;
m_course = 0.0f;
m_bearing = 0.0f;
m_deviation = 0.0f;
m_distance = 0.0f;
m_bearingVisible = true;
m_deviationVisible = true;
m_distanceVisible = true;
m_devBarDeltaX_new = 0.0f;
m_devBarDeltaX_old = 0.0f;
m_devBarDeltaY_new = 0.0f;
m_devBarDeltaY_old = 0.0f;
}
void qfi_NAV::updateView()
{
m_scaleX = (float)width() / (float)m_originalWidth;
m_scaleY = (float)height() / (float)m_originalHeight;
m_itemCrsArrow->setRotation( -m_heading + m_course );
m_itemHdgBug->setRotation( -m_heading + m_headingBug );
m_itemHdgScale->setRotation( -m_heading );
if ( m_bearingVisible )
{
m_itemBrgArrow->setVisible( true );
m_itemBrgArrow->setRotation( -m_heading + m_bearing );
}
else
{
m_itemBrgArrow->setVisible( false );
}
if ( m_deviationVisible )
{
m_itemDevBar->setVisible( true );
m_itemDevScale->setVisible( true );
float angle_deg = -m_heading + m_course;
# ifndef M_PI
float angle_rad = 3.14159265358979323846 * angle_deg / 180.0f;
# else
float angle_rad = M_PI * angle_deg / 180.0f;
# endif
float sinAngle = sin( angle_rad );
float cosAngle = cos( angle_rad );
m_itemDevBar->setRotation( angle_deg );
m_itemDevScale->setRotation( angle_deg );
float delta = m_originalPixPerDev * m_deviation;
m_devBarDeltaX_new = m_scaleX * delta * cosAngle;
m_devBarDeltaY_new = m_scaleY * delta * sinAngle;
m_itemDevBar->moveBy( m_devBarDeltaX_new - m_devBarDeltaX_old, m_devBarDeltaY_new - m_devBarDeltaY_old );
}
else
{
m_itemDevBar->setVisible( false );
m_itemDevScale->setVisible( false );
m_devBarDeltaX_new = m_devBarDeltaX_old;
m_devBarDeltaY_new = m_devBarDeltaY_old;
}
m_itemCrsText->setPlainText( QString("CRS %1").arg( m_course , 3, 'f', 0, QChar('0') ) );
m_itemHdgText->setPlainText( QString("HDG %1").arg( m_headingBug , 3, 'f', 0, QChar('0') ) );
if ( m_distanceVisible )
{
m_itemDmeText->setVisible( true );
m_itemDmeText->setPlainText( QString("%1 NM").arg( m_distance, 5, 'f', 1, QChar(' ') ) );
}
else
{
m_itemDmeText->setVisible( false );
}
m_scene->update();
centerOn( width() / 2.0f , height() / 2.0f );
}