日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]在文章之前,首先看看這篇文章要實(shí)現(xiàn)的效果: 數(shù)據(jù)拾取就是在鼠標(biāo)經(jīng)過線條時(shí),會(huì)捕獲一些特征數(shù)據(jù),上圖是捕獲離鼠標(biāo)最接近的點(diǎn)。Qwt提供了拾取數(shù)據(jù)的現(xiàn)成的類,同時(shí)也留有非常好的接口,用戶可以任意擴(kuò)展,下面

在文章之前,首先看看這篇文章要實(shí)現(xiàn)的效果:

數(shù)據(jù)拾取就是在鼠標(biāo)經(jīng)過線條時(shí),會(huì)捕獲一些特征數(shù)據(jù),上圖是捕獲離鼠標(biāo)最接近的點(diǎn)。

Qwt提供了拾取數(shù)據(jù)的現(xiàn)成的類,同時(shí)也留有非常好的接口,用戶可以任意擴(kuò)展,下面就介紹Qwt專門負(fù)責(zé)拾取數(shù)據(jù)及鼠標(biāo)跟蹤用的QwtPicker及其子類。并對(duì)其擴(kuò)展,構(gòu)建一個(gè)用于顯示鼠標(biāo)經(jīng)過圖像時(shí)捕獲最近點(diǎn)的拾取器。

拾取器

Qwt拾取器QwtPicker,用于顯示鼠標(biāo)經(jīng)過圖像時(shí)的信息,內(nèi)置了一些坐標(biāo)變換和鼠標(biāo)位置及動(dòng)作等函數(shù)

QwtPicker

QwtPicker的繼承關(guān)系如下圖所示

這個(gè)類可以捕獲當(dāng)前鼠標(biāo)位置及動(dòng)作,同時(shí)使用戶在圖表上顯示一些特殊的信息。

拾取器的”橡皮圈“(Rubber Band)

所謂橡皮圈,就是在圖表上的一些附加顯示
QwtPicker有個(gè)QwtPicker::RubberBand的枚舉,此枚舉例舉了默認(rèn)的橡皮圈:

HLineRubberBand
A horizontal line ( only for QwtPickerMachine::PointSelection )

VLineRubberBand
A vertical line ( only for QwtPickerMachine::PointSelection )

CrossRubberBand
A crosshair ( only for QwtPickerMachine::PointSelection )

RectRubberBand
A rectangle ( only for QwtPickerMachine::RectSelection )

EllipseRubberBand
An ellipse ( only for QwtPickerMachine::RectSelection )

PolygonRubberBand
A polygon ( only for QwtPickerMachine::PolygonSelection )

UserRubberBand
Values >= UserRubberBand can be used to define additional rubber bands.

HLineRubberBand是一個(gè)水平線,VLineRubberBand是一個(gè)垂直線,CrossRubberBand是十字線,如下圖所示:

坐標(biāo)變換

在重寫拾取器之前需要先了解qwt的一些函數(shù),其中最重要的就是坐標(biāo)變換問題
由于qwt是一個(gè)繪圖控件,圖形有圖形刻度的坐標(biāo),控件有控件的坐標(biāo),可能圖形坐標(biāo)x軸是0到100萬,y軸是0到10萬,這個(gè)圖卻在屏幕上只有x方向600像素,y方向400像素,這時(shí),鼠標(biāo)在圖形屏幕上點(diǎn)(200,200)位置,對(duì)應(yīng)圖形坐標(biāo)的位置是多少,這需要一個(gè)轉(zhuǎn)變,QwtPlotPicker內(nèi)置兩個(gè)函數(shù)實(shí)現(xiàn)圖形屏幕坐標(biāo)到圖形數(shù)值坐標(biāo)的轉(zhuǎn)換以及逆轉(zhuǎn)換:

把圖形數(shù)值坐標(biāo)轉(zhuǎn)換為屏幕坐標(biāo):

QRect???transform?(const?QRectF?&)?const
QPoint??transform?(const?QPointF?&)?const

把屏幕坐標(biāo)轉(zhuǎn)換為圖形數(shù)值坐標(biāo):

QRectF?invTransform?(const?QRect?&)?const
QPointF?invTransform?(const?QPoint?&)?const

有了這兩個(gè)函數(shù),就可以方便的對(duì)坐標(biāo)進(jìn)行轉(zhuǎn)換了。

自定義拾取器

雖然Qwt內(nèi)置了幾種常用的”橡皮圈“,但是使用者肯定有許多不一樣的需求,例如本文開頭顯示的圖片所示,隨著鼠標(biāo)的移動(dòng),自動(dòng)捕抓最近的點(diǎn),并把最近點(diǎn)的信息顯示出來,且文字顏色也有相應(yīng)的改變,這種特殊要求,就必須自己重寫QwtPicker

重寫QwtPicker主要需要重寫如下虛函數(shù):

//用于控制顯示文字內(nèi)容及區(qū)域的:
virtual?QwtText?????trackerText?(const?QPoint?&pos)?const
virtual?QRect???trackerRect?(const?QFont?&)?const
//用于控制’橡皮筋‘RubberBand的繪制的
virtual?void????drawRubberBand?(QPainter?*)?const
//用于控制追蹤鼠標(biāo)顯示的內(nèi)容(默認(rèn)是顯示文字及一個(gè)矩形背景)
virtual?void????drawTracker?(QPainter?*)?const

drawRubberBand

為了實(shí)現(xiàn)上面追蹤最近點(diǎn)的拾取器
這里自定義一個(gè)拾取器,繼承于QwtPlotPicker

頭文件:

#includeclass?QwtPlotCurve;
class?SAXYDataTracker:?public?QwtPlotPicker
{
public:
????SAXYDataTracker(QWidget?*?canvas);
protected:
????virtual?void?drawRubberBand?(QPainter?*painter)?const;
};

實(shí)現(xiàn)文件:

SAXYDataTracker::SAXYDataTracker(QWidget*?canvas)?:
????QwtPlotPicker(?canvas?)
{
????setTrackerMode(?QwtPlotPicker::ActiveOnly?);
????setRubberBand(?UserRubberBand??);
????setStateMachine(?new?QwtPickerTrackerMachine()?);
}

void?SAXYDataTracker::drawRubberBand(QPainter*?painter)?const
{
????if?(?!isActive()?||?rubberBand()?==?NoRubberBand?||
????????rubberBandPen().style()?==?Qt::NoPen?)
????{
????????return;
????}
????QPolygon?pickedPoint?=?pickedPoints?();
????if(pickedPoint.count?()?<?1)
????????return;
????QwtPlotPicker::drawRubberBand?(painter);
????//獲取鼠標(biāo)的客戶坐標(biāo)位置
????const?QPoint?pos?=?pickedPoint[0];

????QwtPainter::drawLine(?painter,?pos.x(),
????pos.y(),?0,0?);
}

這里只做一個(gè)簡單的實(shí)現(xiàn),就是繪制一條線到(0,0)點(diǎn)

drawRubberBand 是在繪圖畫布上進(jìn)行重繪,在QwtPickerTrackerMachine的狀態(tài)下,只要鼠標(biāo)移動(dòng)就會(huì)觸發(fā)

上面只是一個(gè)小例子,大家可以忽略,請(qǐng)看下面詳細(xì)教程:

最近點(diǎn)捕獲拾取器 求最近點(diǎn)

QwtPlotCurve提供了求最近點(diǎn)的函數(shù)int QwtPlotCurve::closestPoint(const QPoint& _pos_,double * _dist_ = NULL)const
效果是找到鼠標(biāo)最近的一個(gè)點(diǎn):

不過,注意,此函數(shù)是遍歷整個(gè)曲線所有點(diǎn)來求取的,在曲線點(diǎn)數(shù)非常多時(shí),謹(jǐn)慎使用

自定義最近點(diǎn)捕獲Picker

定義求取圖形最近點(diǎn)的函數(shù)
頭文件:

#includeclass?QwtPlotCurve;
class?QwtPlotItem;
class?SAXYDataTracker:?public?QwtPlotPicker
{
public:
????SAXYDataTracker(QWidget?*?canvas);

protected:
????virtual?QwtText?trackerTextF(const?QPointF?&?pos)?const;
????virtual?QRect?trackerRect(const?QFont?&?font)?const;
????virtual?void?drawRubberBand?(QPainter?*painter)?const;
????void?calcClosestPoint(const?QPoint&?pos);
private:
????///
????///?brief?記錄最近點(diǎn)的信息
????///
????class?closePoint
????{
????public:
????????closePoint();
????????QwtPlotCurve?*?curve()?const{return?this->m_curve;}
????????void?setCurve(QwtPlotCurve?*?cur);
????????bool?isValid()?const;
????????QPointF?getClosePoint()?const;
????????int?index()?const{return?this->m_index;}
????????void?setIndex(int?i){this->m_index?=?i;}
????????double?distace()?const{return?this->m_distace;}
????????void?setDistace(double?d){this->m_distace?=?d;}
????????void?setInvalid();
????private:
????????QwtPlotCurve?*m_curve;
????????int?m_index;
????????double?m_distace;
????};
????closePoint?m_closePoint;
private?slots:
????//捕獲鼠標(biāo)移動(dòng)的槽
????void?mouseMove(const?QPoint?&pos);
public?slots:
????void?itemAttached(QwtPlotItem*?plotItem,bool?on);
};

源文件: (跳過吧?。?/p>

#include "SAXYDataTracker.h"
#include

下面等我慢慢介紹上面的代碼:

求全局最近點(diǎn)

函數(shù):
void calcClosestPoint(const QPoint& pos);
是用于求取全局最近點(diǎn)的,為了防止頻繁求取,我們把得到的最近點(diǎn)信息保存下來,因此建立了一個(gè)內(nèi)部類:

///
///?brief?記錄最近點(diǎn)的信息
///
class?closePoint
{
public:
???closePoint();
???QwtPlotCurve?*?curve()?const{return?this->m_curve;}
???void?setCurve(QwtPlotCurve?*?cur);
???bool?isValid()?const;
???QPointF?getClosePoint()?const;
???int?index()?const{return?this->m_index;}
???void?setIndex(int?i){this->m_index?=?i;}
???double?distace()?const{return?this->m_distace;}
???void?setDistace(double?d){this->m_distace?=?d;}
???void?setInvalid();
private:
???QwtPlotCurve?*m_curve;
???int?m_index;
???double?m_distace;
};

此類的作用就是保存最近點(diǎn)的信息,這里并沒有把那個(gè)點(diǎn)保存了下來,而是保存了對(duì)應(yīng)的曲線和索引。
通過QPointF getClosePoint() const函數(shù)可以獲取最近點(diǎn)。
void calcClosestPoint(const QPoint& pos);的實(shí)現(xiàn)就是遍歷plot里的所有曲線,并求取其最近的那個(gè)點(diǎn),并把信息保存在closePoint里,這里連點(diǎn)距離借用了Qt的QLineF類來求,當(dāng)然自己寫也是很簡單的事情。
函數(shù)void calcClosestPoint(const QPoint& pos)里,首先把屏幕坐標(biāo)轉(zhuǎn)換為坐標(biāo)軸的數(shù)值坐標(biāo)

//把屏幕坐標(biāo)轉(zhuǎn)換為圖形的數(shù)值坐標(biāo)
QPointF?mousePoint?=?invTransform(pos);

并用一個(gè)double記錄最短的距離,初始化為double的最大值,用到了stl里的numeric_limits函數(shù)

std::numeric_limits::max?();

最后檢查最大值的曲線與上一次的曲線是否一樣,不一樣就更換RubberBand的顏色,實(shí)現(xiàn)RubberBand的顏色跟隨曲線一致

//說明最近點(diǎn)的曲線更換了,標(biāo)記線的顏色換為當(dāng)前曲線的顏色
if(m_closePoint.isValid?()?&&?oldCur!=m_closePoint.curve?())
{
?????QPen?p(m_closePoint.curve?()->pen?());
?????p.setWidth?(1);
?????setRubberBandPen?(p);
}

繪制鼠標(biāo)到最近點(diǎn)的連線

最近點(diǎn)求取后,就是繪制鼠標(biāo)到最近點(diǎn)的連線

本例里重載了三個(gè)QwtPicker的虛函數(shù):

????virtual?QwtText?trackerTextF(const?QPointF?&?pos)?const;
????virtual?QRect?trackerRect(const?QFont?&?font)?const;
????virtual?void?drawRubberBand?(QPainter?*painter)?const;

其中virtual void drawRubberBand (QPainter *painter) const;是為了繪制橡皮筋(RubberBand)其實(shí)就是圖表的繪制用的。

void?SAXYDataTracker::drawRubberBand(QPainter*?painter)?const
{
????if?(?!isActive()?||?rubberBand()?==?NoRubberBand?||
????????rubberBandPen().style()?==?Qt::NoPen?)
????{
????????return;
????}
????if(!m_closePoint.isValid?())
????????return;
????QPolygon?pickedPoint?=?pickedPoints?();
????if(pickedPoint.count?()?<?1)
????????return;
????//獲取鼠標(biāo)的客戶坐標(biāo)位置
????const?QPoint?pos?=?pickedPoint[0];
????const?QPointF?closePoint?=?m_closePoint.getClosePoint?();
????const?QPoint?cvp?=?transform?(closePoint);
????QwtPainter::drawLine?(painter,pos,cvp);
????QRect?r(0,0,10,10);
????r.moveCenter?(cvp);
????QwtPainter::drawRect?(painter,r);
}

QPolygon pickedPoint = pickedPoints ();函數(shù)獲取鼠標(biāo)當(dāng)前的點(diǎn),當(dāng)然,用trackerPosition 一樣能獲取,在這里效果一致:

//獲取鼠標(biāo)的客戶坐標(biāo)位置
const?QPoint?pos?=?trackerPosition?();
if(pos.isNull?())
????return;

m_closePoint.getClosePoint獲取最近的那個(gè)點(diǎn),此點(diǎn)是數(shù)值結(jié)果,需要轉(zhuǎn)變?yōu)槠聊蛔鴺?biāo),因此使用了QwtPlotPicker::transform函數(shù),把數(shù)值結(jié)果轉(zhuǎn)換為屏幕坐標(biāo)

const?QPointF?closePoint?=?m_closePoint.getClosePoint?();
const?QPoint?cvp?=?transform?(closePoint);

之后就是繪制圖形了:

QwtPainter::drawLine?(painter,pos,cvp);
QRect?r(0,0,10,10);
r.moveCenter?(cvp);
QwtPainter::drawRect?(painter,r);

Qwt把繪圖的函數(shù)封裝在QwtPainter的類里,此類全部為靜態(tài)函數(shù),相當(dāng)于命名空間,負(fù)責(zé)所有QPainter的操作。這樣可以在const函數(shù)里使用QPainter。

這時(shí)就能繪制一個(gè)線,從鼠標(biāo)的位置連接到最近點(diǎn)的位置。

繪制文本

QwtPicker的跟蹤文本繪制有兩個(gè)虛函數(shù):

????virtual?QwtText?trackerTextF(const?QPointF?&?pos)?const;
????virtual?QRect?trackerRect(const?QFont?&?font)?const;

virtual QwtText trackerTextF(const QPointF & pos) const;負(fù)責(zé)顯示的內(nèi)容
virtual QRect trackerRect(const QFont & font) const;負(fù)責(zé)繪制的區(qū)域

繪制區(qū)域需要根據(jù)內(nèi)容來設(shè)定:

QRect?SAXYDataTracker::trackerRect(const?QFont&?font)?const
{
????QRect?r?=?QwtPlotPicker::trackerRect(?font?);
????r?+=?QMargins(5,5,5,5);
????return?r;
}

QwtPlotPicker::trackerRect( font );可獲取默認(rèn)的繪制區(qū)域,此區(qū)域緊緊包裹著文字,為了好看點(diǎn),讓區(qū)域外擴(kuò)5像素r += QMargins(5,5,5,5);

trackerTextF用來控制顯示的信息

QwtText SAXYDataTracker::trackerTextF(const QPointF& pos) const
{
 ? ?QwtText trackerText;
 ? ?if(!m_closePoint.isValid ())
 ? ? ? ?return trackerText;
 ? ?trackerText.setColor( Qt::black );
 ? ?QColor lineColor = m_closePoint.curve()->pen ().color ();
 ? ?QColor bkColor(lineColor);
 ? ?bkColor.setAlpha (30);
 ? ?trackerText.setBorderPen( m_closePoint.curve()->pen () );
 ? ?trackerText.setBackgroundBrush( bkColor );
 ? ?QPointF point = m_closePoint.getClosePoint ();
 ? ?QString info = QStringLiteral("y:%2
") ? ? ? ? ? ? ? ? ? .arg(lineColor.name ()).arg(point.y ()) ? ? ? ? ? ? ? ? ? + ? ? ? ? ? ? ? ? ? QStringLiteral("x:%2") ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.arg(lineColor.name ()).arg(point.x ()); ? ?trackerText.setText( info ); ? ?trackerText.setBorderRadius (5); ? ?return trackerText; }

QwtText 支撐html文本的顯示,同時(shí)能比較方便的設(shè)置背景及畫刷,這里使用html把文字用與曲線相同的顏色繪制,背景使用曲線相同顏色的背景,不過透明度更低。
最終效果如下:

這是有5條325000個(gè)點(diǎn)的數(shù)據(jù)線的繪制情況:

可以看到C++的響應(yīng)速度還是很可觀的

要點(diǎn) Qwt圖形數(shù)值坐標(biāo)轉(zhuǎn)換為屏幕坐標(biāo)以及屏幕坐標(biāo)轉(zhuǎn)換為數(shù)值坐標(biāo):

QRect???transform?(const?QRectF?&)?const
QPoint??transform?(const?QPointF?&)?const

QRectF?invTransform?(const?QRect?&)?const
QPointF?invTransform?(const?QPoint?&)?const

QwtPlotCurve求最近點(diǎn):
QwtPlotCurve提供了求最近點(diǎn)的函數(shù)int QwtPlotCurve::closestPoint(const QPoint& _pos_,double * _dist_ = NULL)const

本文源碼都在原文中

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉