添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

发现QCustomPlot自带框选放大功能,不需要自己写,

直接启用就好了:

plot->selectionRect()->setPen(QPen(Qt::black,1,Qt::DashLine));//设置选框的样式:虚线
plot->selectionRect()->setBrush(QBrush(QColor(0,0,100,50)));//设置选框的样式:半透明浅蓝
plot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);

不过使用官方的框选放大功能,也带来一个毛病,就是鼠标左、右、中,三个键都变成了框选放大,失去了拖拽平移功能,这用起来很不爽,我们改一下官方源码,使之同时具备这种功能:1、左键框选时进行放大,2、滚轮按下并拖拽时,可平移曲线,3、右键单击弹出功能菜单。

为实现这3个功能,首先我们要把官方的平移功能,由左键改到右键上,见下文。然后我们再把官方的框选功能限制在左键上,如下图两处修改。齐活儿,enjoy it。

----------------以下为原文----------------

QCustomPlot原本是不带这个功能的,不过既然有源码,也好改。

原理很简单:1、记录鼠标按下/弹起的像素坐标,并转换为图像坐标,然后把轴的显示范围重新设置一下即可。

2、如果在释放鼠标前按下了ESC键,那么就取消框选放大功能。

先看一下效果:用鼠标画出一个矩形区域,释放鼠标后即可把图像放大到框选区。

由于官方默认左键是平移曲线,我们先把平移功能改到右键(或者滚轮中键,根据你的喜好)上去,直接在这个函数里
void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details)改就行了,把Qt::LeftButton改成Qt::RightButton即可。

下面开始实现框选放大功能:

1、在QCustomPlot类中添加private变量:

private:
  QRubberBand *rb;
  QPoint startPos;
  bool cancelRb;

2、直接在h文件中,QCustomPlot类中添加ESC按键处理函数

virtual void QCustomPlot::keyPressEvent(QKeyEvent *e)
    if(e->key() == Qt::Key_Escape) {
        cancelRb = true; //记录标志位,以便释放鼠标后不执行缩放代码
        rb->hide();//隐藏选择框

3、在QCustomPlot的3个鼠标事件函数添加代码
 

0、在构造函数QCustomPlot::QCustomPlot(QWidget *parent)的初始化列表中添加:
  ,rb(new QRubberBand(QRubberBand::Rectangle, this))
  ,startPos(0, 0)
1、左键按下时,记录坐标起点
    在QCustomPlot::mousePressEvent(QMouseEvent *event)中添加:
    if(event->buttons() & Qt::LeftButton)
        startPos = event->pos();
        cancelRb = false;
        rb->resize(0, 0);
        rb->show();
2、左键按下并移动时,绘制矩形框
    在void QCustomPlot::mouseMoveEvent(QMouseEvent *event)中添加:
    if(event->buttons() & Qt::LeftButton)
        QRect normalRect = QRect(startPos, event->pos()).normalized();//任意两点定义矩形
        rb->setGeometry(normalRect);
3、左键弹起时,记录终点坐标,并把曲线放大到【起点、终点】围成的矩形框中
    在void QCustomPlot::mouseReleaseEvent(QMouseEvent *event)中添加:
    if(event->button() == Qt::LeftButton)
        rb->hide();
        if(!cancelRb)
            QRect normalRect = QRect(startPos, event->pos()).normalized();
            rb->setGeometry(normalRect);
            this->xAxis->setRange(xAxis->pixelToCoord(normalRect.left()),
                                  xAxis->pixelToCoord(normalRect.right()));
            this->yAxis->setRange(yAxis->pixelToCoord(normalRect.bottom()),
                                  yAxis->pixelToCoord(normalRect.top()));
            this->replot();//立即刷新图像

所有代码就这些。

以上代码中需要说明的就3点:

1、框选区使用了QT自带的橡皮筋选区QRubberBand,这玩意在我看来就是个半透明带颜色的QWidget,其实我们完全可以用QWidget来显示鼠标画出的矩形区,只不过有点麻烦而已,需要我们自己设置QWidget的漂亮样式(边框、蓝色半透明等)。总的来看,不如直接用QRubberBand来显示选区方便。

2、记录矩形选区
鼠标按下时记录一次坐标,释放时再记录一次坐标,这两个点构成的矩形就作为选区,只不过这里有个问题,如果你是从左上向右下进行框选这没毛病,如果从右下向左上进行框选,右下点和左上点,这两个点不符合QRec的构造函数形参要求,这样直接用来设置rb->setGeometry(rect);就会显示不出来,因为setGeometry的本质形参是(x,y,w,h),右下点和左上点相减得出的宽度w和高度h都是负的,左下和右上点得出的w+y-等等,只有左上和右下才能得出w+y+。当然这个问题可以程序员自行判断两个点的位置,并重新构造一个合理的x、y、w、h,但是我们没必要费这个劲,QRect::normalized()就是做这个事情的,执行normalized之后,QRect::top/bottom/left/right就是矩形区真正的上下左右。

3、QWidget的像素坐标转换为曲线的XY轴坐标,用的是xAxis->pixelToCoord(xx),反向功能函数为xAxis->coordTopixel(xx)

QCustomPlot原本是不带这个功能的,不过既然有源码,也好改。原理很简单:1、记录鼠标按下/弹起的像素坐标,并转换为图像坐标,然后把轴的显示范围重新设置一下即可。2、如果在释放鼠标前按下了ESC键,那么就取消框选放大功能。先看一下效果:用鼠标画出一个矩形区域,释放鼠标后即可把图像放大到框选区。由于官方默认左键是平移曲线,我们先把平移功能改到右键(或者滚轮中键,根据你...
QCustomPlot-用鼠标矩形框进行框选放大一、QCustomPlot自带框选放大功能 一、QCustomPlot自带框选放大功能 发现QCustomPlot自带框选放大功能,不需要自己写,直接启用就好了: plot->selectionRect()->setPen(QPen(Qt::black,1,Qt::DashLine));//设置选框的样式:虚线 plot->selectionRect()->setBrush(QBrush(QColor(0,0,100,50)));//设
QCustomPlot是一个基于Qt C++的图形库,用于绘制和数据可视化 - 制作漂亮的2D图 - 曲线图、趋势图、坐标图、柱状图等,并为实时可视化应用程序提供高性能服务。它没有进一步的依赖关系,并有着良好的文档记录。 QCustomPlot可以导出为各种格式,比如:PDF文件和位图(如:PNG、JPG、BMP)。 可在自...
欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex数学公式 UML序列图和流程图 离线写博客 导入导出Markdown文件 丰富的快捷键 加粗 Ctrl + B 斜体 Ctrl + I 引用 Ctrl
前面一章已经记录了 怎么进行框选放大了。 添加如下代码: customPlot->selectionRect()->setPen(QPen(Qt::black,1,Qt::DashLine));//设置选框的样式:虚线 customPlot->selectionRect()->setBrush(QBrush(QColor(0,0,100,50)));//设置选框的样式:半透明浅蓝 customPlot->setSelectionRectMode(QCP::Selection
要通过鼠标轨迹画矩形框,可以结合使用QCustomPlot鼠标事件和QCPItemRect类。可以按照以下步骤进行操作: 1. 创建一个QCPItemRect对象: QCPItemRect *rect = new QCPItemRect(customPlot); rect->setPen(QPen(Qt::red)); rect->setBrush(QBrush(Qt::blue)); 2. 实现鼠标事件: void MainWindow::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) rect->topLeft->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); rect->bottomRight->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); rect->setVisible(true); ui->customPlot->replot(); void MainWindow::mouseMoveEvent(QMouseEvent *event) if (event->buttons() == Qt::LeftButton) rect->bottomRight->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); ui->customPlot->replot(); void MainWindow::mouseReleaseEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) rect->setVisible(false); ui->customPlot->replot(); 其中,鼠标按下时记录矩形框左上角的坐标,鼠标移动时更新矩形框右下角的坐标并重新绘制,鼠标释放时隐藏矩形框并重新绘制。 完整的代码示例: void MainWindow::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) rect->topLeft->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); rect->bottomRight->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); rect->setVisible(true); ui->customPlot->replot(); void MainWindow::mouseMoveEvent(QMouseEvent *event) if (event->buttons() == Qt::LeftButton) rect->bottomRight->setCoords(ui->customPlot->xAxis->pixelToCoord(event->pos().x()), ui->customPlot->yAxis->pixelToCoord(event->pos().y())); ui->customPlot->replot(); void MainWindow::mouseReleaseEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) rect->setVisible(false); ui->customPlot->replot(); void MainWindow::setupPlot() // ... rect = new QCPItemRect(ui->customPlot); rect->setPen(QPen(Qt::red)); rect->setBrush(QBrush(Qt::blue)); rect->setVisible(false);