qwt 之 QwtPlotPicker
QwtPlotMarker 和 QwtPlotPicker 是 Qwt 库中用于增强 QwtPlot 功能的两个重要类。它们分别用于在图中添加标记和实现交互式的选择或拖动功能。
QwtPlotPicker 提供了交互式的选择工具,它允许用户通过鼠标点击或拖动来选择图表中的数据点或区域。这对于实现缩放、平移或者其他基于用户输入的操作非常有用。
主要功能
• 选择模式:可以选择不同的选择模式,如点选择、矩形选择、多边形选择等。
• 事件处理:通过信号和槽机制响应用户的交互行为(如鼠标点击、拖动等)。
• 坐标转换:提供从屏幕坐标到数据坐标的转换方法。
• 自定义绘图:可以通过重写绘制函数来自定义选择框或其他视觉反馈。
示例代码 1
#include <QApplication>
#include <QwtPlot>
#include <QwtPlotCurve>
#include <QwtPlotPicker>
#include <QwtPickerMachine>
#include <QwtPlotPanner> // 如果需要平移功能
class PickerTracker : public QObject {
Q_OBJECT
public slots:
void trackerText(const QString &text) {
qDebug() << "Tracker Text:" << text;
}
void selected(const QPointF &pos) {
qDebug() << "Selected Position:" << pos;
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建并配置 QwtPlot
QwtPlot plot;
plot.setTitle("QwtPlotPicker Example");
// 添加一条曲线
QwtPlotCurve *curve = new QwtPlotCurve("Sample Curve");
QVector<double> xData = {0.0, 1.0, 2.0, 3.0, 4.0};
QVector<double> yData = {0.0, 1.0, 4.0, 9.0, 16.0};
curve->setSamples(xData, yData);
curve->attach(&plot);
// 创建并配置 QwtPlotPicker
QwtPlotPicker *picker = new QwtPlotPicker(
QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection,
QwtPlotPicker:: RubberBand, QwtPicker::AlwaysOn, plot.canvas()
);
picker->setStateMachine(new QwtPickerDragPointMachine()); // 设置选择模式
// 连接信号和槽
PickerTracker tracker;
connect(picker, SIGNAL(trackerText(const QString &)), &tracker, SLOT(trackerText(const QString &)));
connect(picker, SIGNAL(selected(const QPointF &)), &tracker, SLOT(selected(const QPointF &)));
// 如果需要平移功能
QwtPlotPanner *panner = new QwtPlotPanner(plot.canvas());
panner->setMouseButton(Qt::MidButton); // 使用中间按钮进行平移
// 显示窗口
plot.resize(800, 600);
plot.show();
return app.exec();
}
示例代码 2
class DistancePicker : public QwtPlotPicker
{
public:
DistancePicker( QWidget* canvas )
: QwtPlotPicker( canvas )
{
setTrackerMode( QwtPicker::ActiveOnly );
setStateMachine( new QwtPickerDragLineMachine() );
setRubberBand( QwtPlotPicker::PolygonRubberBand );
}
virtual QwtText trackerTextF( const QPointF& pos ) const QWT_OVERRIDE
{
QwtText text;
const QPolygon points = selection();
if ( !points.isEmpty() )
{
QString num;
num.setNum( QLineF( pos, invTransform( points[0] ) ).length() );
QColor bg( Qt::white );
bg.setAlpha( 200 );
text.setBackgroundBrush( QBrush( bg ) );
text.setText( num );
}
return text;
}
};
setStateMachine 方法
QwtPlotPicker 的 setStateMachine() 方法用于设置选择器的状态机,这决定了用户如何与图表进行交互。Qwt 提供了几种预定义的状态机类,每种状态机都实现了一种特定的交互模式。以下是 Qwt 中常见的几种状态机:
- QwtPickerMachine
这是所有其他状态机的基础类,它本身不提供具体的行为,但可以作为自定义状态机的起点。 - QwtPickerClickPointMachine
这种状态机允许用户通过单击鼠标来选择一个点。每次点击都会触发一个选定点的信号。
• 适用场景:当你只需要用户在图表上点击以选择单个数据点时使用。 - QwtPickerDragPointMachine
这种状态机允许用户通过拖动鼠标来选择一个点。用户按下鼠标按钮并移动到新的位置后释放按钮,这个新位置会被视为选定的点。
• 适用场景:适用于需要更精确地选择或调整图表上的某个点的情况。 - QwtPickerRectMachine
这种状态机允许用户通过拖动鼠标绘制一个矩形区域来选择多个点。矩形的选择框会随着鼠标的移动而更新,直到用户释放鼠标按钮。
• 适用场景:当你需要让用户选择一个矩形区域内的所有数据点时使用。 - QwtPickerPolygonMachine
这种状态机允许用户通过连续点击来创建一个多边形区域,最终形成一个封闭的多边形选择区域。用户可以通过双击或者按下一个特定的键(如 Enter)来完成多边形的选择。
• 适用场景:适用于复杂形状的选择区域,比如非矩形的不规则区域。
setStateMachine 使用示例
#include <QApplication>
#include <QwtPlot>
#include <QwtPlotCurve>
#include <QwtPlotPicker>
#include <QwtPickerMachine>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建并配置 QwtPlot
QwtPlot plot;
plot.setTitle("QwtPlotPicker Example");
// 添加一条曲线
QwtPlotCurve *curve = new QwtPlotCurve("Sample Curve");
QVector<double> xData = {0.0, 1.0, 2.0, 3.0, 4.0};
QVector<double> yData = {0.0, 1.0, 4.0, 9.0, 16.0};
curve->setSamples(xData, yData);
curve->attach(&plot);
// 创建并配置 QwtPlotPicker
QwtPlotPicker *picker = new QwtPlotPicker(
QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::PointSelection,
QwtPlotPicker::RubberBand, QwtPicker::AlwaysOn, plot.canvas()
);
// 设置状态机
picker->setStateMachine(new QwtPickerClickPointMachine()); // 单点选择
// 或者
// picker->setStateMachine(new QwtPickerDragPointMachine()); // 拖动选择点
// 或者
// picker->setStateMachine(new QwtPickerRectMachine()); // 矩形区域选择
// 或者
// picker->setStateMachine(new QwtPickerPolygonMachine()); // 多边形区域选择
// 显示窗口
plot.resize(800, 600);
plot.show();
return app.exec();
}
自定义状态机
如果你的需求超出了上述预定义状态机的功能,你可以继承 QwtPickerMachine 类并实现自己的状态机逻辑。
综合应用
当你想要创建一个带有交互功能的图表时,通常步骤如下:
- 创建 QwtPlot 实例。
- 添加绘图项,如 QwtPlotCurve 或其他类型的绘图项。
- 创建并配置 QwtPlotMarker 来添加静态标记。
- 创建并配置 QwtPlotPicker 来实现交互功能,并根据需要设置选择模式和事件处理逻辑。
- 连接信号和槽,以便对用户的交互行为做出响应。
- 如果需要,还可以添加其他交互组件,如 QwtPlotPanner 用于平移功能。