QCustomPlot Discussion and Comments

Advice for the creation of an interactive ROI objectReturn to overview

Dear all,

First of all, I would like to thank the developer of this library for the amazing job that has been done. I'm clearly impressed by the quality of the code and the performance of the library.

I'm pretty new to QCustomPlot and to C++ from a general manner (started 6 days ago ;-)). I've been using Python for several years now for simple scientific scripting programming but also for the development of GUI applications using PyQt. One of my need for these GUI apps is the ability to have some interactive tools on plots (either simple charts or images). Up to now, I used PyQtGraph which did a very incredible job on that aspect (and many others). For now (but I may be wrong), there is not the same amount of interactivity out-of-the box with QCustomPlot, that is why I would like to add some of the functionality I found in other libraries in QCustomPlot. It seems simple to do as, from my point of view with my limited knowledge of QCustomPlot so far, QCustomPlot seems to offer solid functionnalities that can be used to build complex objects.

The first one was quite simple to add : I needed a draggable InfiniteLine to point out a specific area of my plot. The InfiniteLine is simply a horizontal or vertical QCPItemStraightLine. The draggable functionality was pretty simple to add. Here is my solution (hope it will be useful for others, and my solution is correct)

infiniteline.h

#ifndef INFINITELINE_H
#define INFINITELINE_H

#include "qcustomplot.h"

class QMouseEvent;
class QVariant;
class QPointF;

class InfiniteLine : public QCPItemStraightLine
{
    Q_OBJECT

public:
    InfiniteLine(QCustomPlot *parentPlot, Qt::Orientation mOrientation);
    ~InfiniteLine();

    Qt::Orientation orientation() const { return m_orientation; }

protected:
    Qt::Orientation m_orientation;

protected slots:
    void mousePressEvent(QMouseEvent *event, const QVariant &details);
    void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos);
    void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos);

};

#endif // INFINITELINE_H

infiniteline.cpp

#include "infiniteline.h"
#include "qcustomplot.h"
#include <QtGui>

InfiniteLine::InfiniteLine(QCustomPlot *parentPlot, Qt::Orientation orientation)
    : QCPItemStraightLine(parentPlot)
{
    m_orientation = orientation;
}

InfiniteLine::~InfiniteLine()
{

}


void InfiniteLine::mousePressEvent(QMouseEvent *event, const QVariant &details)
{

}


void InfiniteLine::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
{
    if (orientation() == Qt::Horizontal)
    {
        double y = parentPlot()->yAxis->pixelToCoord(event->pos().y());
        point1->setCoords(0, y);
        point2->setCoords(1, y);
    }
    else
    {
        double x = parentPlot()->xAxis->pixelToCoord(event->pos().x());
        point1->setCoords(x, 0);
        point2->setCoords(x, 1);
    }
    parentPlot()->replot();
}


void InfiniteLine::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
{
}

Now I would like to add a Region Of Interest tool. Basically, it a rectangle that has some handles at some specific location (but this can be generalized to Ellipse for example). These handles can be used to change interactively the dimension of the rectangle (let's suppose they are represented as square symbols) or rotate it (let's assume they can be represented as a circle symbol). The rectangle location can be changed by dragging the whole element to another location, or its dimension/orientation can be changed by an interaction with one of the handles. QCustomPlot proposes all the tool to code that. The rectangle will be a QCPItemRect and the handles will be either QCPItemRect of QCPItemEllipse. What I'm not able to do is where to start and how to mix these basic objects into a more complex one. Any help would be highly appreciated! The source code I would write, based on the help I would get, will be of course shared.

Many thanks in advance for your time.

Best regards,

Vincent

Take a look at the creating your own item section in https://www.qcustomplot.com/documentation/classQCPAbstractItem.html

basically it involves overriding the draw function and the selectTest.

I actually saw this page in the documentation before posting here but I was just wondering if an other approach could be used as I just want a combination of already existing item.

There still remains one aspect that is not clear to me, but I first need to think about it before posting something before.

Thank you Ian!