Let's start with a motion picture to see the effect :
Support mouse translation , Scroll zoom , Frame select and enlarge , Unselect , One click display , Click Show xy Coordinate value .. etc.
The translation function is QCustomPlot Built in functions , See my previous blog post in this series . Frame select and enlarge , Full display and other functions are also mentioned in another blog post .
I'll just talk about it here 2 Three knowledge points :1, Displays the coordinates of the points the mouse points to ,2, Real time scrolling
1, The arrow points to the coordinate point to be displayed , Code steps :
(1) Add new class , inherit QCustomPlot
add to private Member variable :
QCPItemText *textLabel;// Prompt information box when clicking QCPItemLine *arrow;// Arrow for prompt information Initialize them in the construct :
// The following paragraph is from QCustomPlot From the official website /* Prompt box for displaying values */ textLabel = new QCPItemText(this);
textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);// The box is placed in the middle of the upper part
textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
textLabel->position->setCoords(0.5, 0); // place position at center/top of axis
rect textLabel->setFont(QFont(font().family(), 16)); // typeface
textLabel->setPen(QPen(Qt::black)); // colour // Arrow pointing to value : arrow = new
QCPItemLine(this);
arrow->start->setParentAnchor(textLabel->bottom);// The starting point of the arrow is at the midpoint of the bottom border of the prompt box
//arrow->end->setCoords(4, 1.6); // Sets the end of the arrow
arrow->setHead(QCPLineEnding::esSpikeArrow);// Arrow Type
textLabel->setVisible(false);// The prompt box is not visible arrow->setVisible(false);// The arrow is not visible
(2) Override mouse down / Bounce event
void MultiCurvesPlot::mousePressEvent(QMouseEvent *event) {
// After rewriting , Still make the function of the parent class , Otherwise, the drag function will be invalid QCustomPlot::mousePressEvent(event);// Functions of the parent class
if(event->buttons() & Qt::LeftButton)// Press the left mouse button {
textLabel->setVisible(true);// Prompt box visible arrow->setVisible(true);// The arrow is visible double x =
xAxis->pixelToCoord(event->pos().x());// Mouse coordinates converted to XY Coordinates of the axis double y =
yAxis->pixelToCoord(event->pos().y()); arrow->end->setCoords(x, y); // Sets the end of the arrow
QString xTime = QDateTime::fromMSecsSinceEpoch(x *
1000.0).toString("hh:mm:ss.zzz");// Click the X Value to time String
textLabel->setText(QString("x = %1\ny=%2").arg(xTime).arg(y));// display XY value } } void
MultiCurvesPlot::mouseReleaseEvent(QMouseEvent *event) {
QCustomPlot::mouseReleaseEvent(event); if(event->button() ==
Qt::LeftButton)// Left key bounce { textLabel->setVisible(false);// Hide numeric boxes and arrows
arrow->setVisible(false); } }
2, Real time scrolling curves
There are only two things we need to do :1, towards graph Add a new point to the this->graph(graphIdx)->addData(currentTime, y);
2, Real time modification X Display range of axis
In my case ,X Axis is real time , therefore , To make the curve scroll in real time , Just put X The display range of the axis is changed to : from < current time - current X The display width of the axis > reach < current time > that will do ,
So the curve will roll . among , current X The display width of the axis can be changed from xAxis->range().size() read .
be careful : If we receive data points too frequently , We should not refresh the image every time we receive a point , That's too inefficient , It's not necessary . General settings 30ms One refresh is smooth enough , After all, the average movie we download is not enough 30 Frames per second .
therefore , We're in one 30ms Timer slot function : modify X Display range of axis + Refresh image .
The code steps are as follows :
(1) Start in constructor QWidget Built in timer
startTimer(30, Qt::CoarseTimer);// each 30ms Trigger once timeEvent event
(2) rewrite void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; Function to respond to the timeout event of this timer :
void MultiCurvesPlot::timerEvent(QTimerEvent *event) { Q_UNUSED(event);
if(autoScroll)// If Auto scroll is activated { double curSeclf =
(double)(QDateTime::currentMSecsSinceEpoch()) /
1000.0;// Read current time ( because QCustomPlot Supported time value ms The value is in decimal places , therefore /1000.0 It's over )
this->xAxis->setRange(curSeclf - xAxis->range().size(), curSeclf);// Real time adjustment X Display range of axis
} this->replot();// Refresh image }
That's the code , It's simple .
The group number is on the left .
Technology