在文章之前,首先看看这篇文章要实现的效果:
数据拾取就是在鼠标经过线条时,会捕获一些特征数据,上图是捕获离鼠标最接近的点。
Qwt提供了拾取数据的现成的类,同时也留有非常好的接口,用户可以任意扩展,下面就介绍Qwt专门负责拾取数据及鼠标跟踪用的QwtPicker及其子类。并对其扩展,构建一个用于显示鼠标经过图像时捕获最近点的拾取器。
拾取器
Qwt拾取器QwtPicker,用于显示鼠标经过图像时的信息,内置了一些坐标变换和鼠标位置及动作等函数
QwtPicker
QwtPicker的继承关系如下图所示
这个类可以捕获当前鼠标位置及动作,同时使用户在图表上显示一些特殊的信息。
拾取器的”橡皮圈“(Rubber Band)
所谓橡皮圈,就是在图表上的一些附加显示
QwtPicker有个QwtPicker::RubberBand的枚举,此枚举例举了默认的橡皮圈:
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是一个水平线,VLineRubberBand是一个垂直线,CrossRubberBand是十字线,如下图所示:
坐标变换
在重写拾取器之前需要先了解qwt的一些函数,其中最重要的就是坐标变换问题
由于qwt是一个绘图控件,图形有图形刻度的坐标,控件有控件的坐标,可能图形坐标x轴是0到100万,y轴是0到10万,这个图却在屏幕上只有x方向600像素,y方向400像素,这时,鼠标在图形屏幕上点(200,200)位置,对应图形坐标的位置是多少,这需要一个转变,QwtPlotPicker内置两个函数实现图形屏幕坐标到图形数值坐标的转换以及逆转换:
把图形数值坐标转换为屏幕坐标:
QRect transform (const QRectF &) const
QPoint transform (const QPointF &) const
把屏幕坐标转换为图形数值坐标:
QRectF invTransform (const QRect &) const
QPointF invTransform (const QPoint &) const
有了这两个函数,就可以方便的对坐标进行转换了。
自定义拾取器
虽然Qwt内置了几种常用的”橡皮圈“,但是使用者肯定有许多不一样的需求,例如本文开头显示的图片所示,随着鼠标的移动,自动捕抓最近的点,并把最近点的信息显示出来,且文字颜色也有相应的改变,这种特殊要求,就必须自己重写QwtPicker
重写QwtPicker主要需要重写如下虚函数:
//用于控制显示文字内容及区域的:
virtual QwtText trackerText (const QPoint &pos) const
virtual QRect trackerRect (const QFont &) const
//用于控制’橡皮筋‘RubberBand的绘制的
virtual void drawRubberBand (QPainter *) const
//用于控制追踪鼠标显示的内容(默认是显示文字及一个矩形背景)
virtual void drawTracker (QPainter *) const
drawRubberBand
为了实现上面追踪最近点的拾取器
这里自定义一个拾取器,继承于QwtPlotPicker
头文件:
#include
class QwtPlotCurve;
class SAXYDataTracker: public QwtPlotPicker
{
public:
SAXYDataTracker(QWidget * canvas);
protected:
virtual void drawRubberBand (QPainter *painter) const;
};
实现文件:
SAXYDataTracker::SAXYDataTracker(QWidget* canvas) :
QwtPlotPicker( canvas )
{
setTrackerMode( QwtPlotPicker::ActiveOnly );
setRubberBand( UserRubberBand );