Reputation: 159
I'm developing an ECG application. It gets ECG samples in every 2 milliseconds. My drawing mechanism is as below: 1- buffering samples 2- checking buffer every 30 ms and draw samples (about 15 samples). 3- using a QPainterPath in every period.
My sample code is as below, note that in this code i read samples from a file!
1) widget.h file:
class Widget : public QWidget
{
Q_OBJECT
int idx=0;
QTimer timer;
public:
explicit Widget(QWidget *parent=0);
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
QStringList list;
float x=0;
QPointF aa;
public slots:
void changeT(){update();}
};
2) widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent),aa(0,0)
{
connect(&timer,SIGNAL(timeout()),this,SLOT(changeT()));
timer.start(25);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
painter.setPen(QPen(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap));
QPainterPath path;
path.moveTo(aa);
for(int i=idx; i<idx+25 ; i++)
{
QPointF bb(x, list.at(i).toInt());
x+=0.25;
path.quadTo(aa,bb);
aa=bb;
}
idx+=25;
painter.drawPath(path);
QWidget::paintEvent(event);
painter.end();
}
3) main.cpp
#include "widget.h"
bool ECG_data(QStringList& strings)
{
QFile file("/home/amvajnegar/ecg.txt");
if (file.open(QIODevice::ReadOnly))
{
QTextStream in(&file);
while(!in.atEnd())
{
strings<< in.readLine();
}
return true;
}
return false;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList lst;
if(!ECG_data(lst))
{
qDebug()<<"nothing!";
return 0;
}
Widget wid;
wid.list = lst;
wid.show();
return a.exec();
}
now my questions are:
1- when I draw new samples in each period, the application erases previous drawn curve! so I always have just a short part of the curve! how can I fix this problem?
2- on my embedded board CPU usage is 100%. how can I reduce it? for example how can I use bounding rectangle or any other Ideas?
3- Is it better mechanism to plot such curves? (I test QCustomPlot and Qwt >but were not well!)
here is my ecg.txt file thanks.
Upvotes: 1
Views: 1379
Reputation: 159
I found the solution: I had to set bounding rectangle for QWidget update method. This function takes a rectangle and updates just pixels inside it. Here is my new implementations for Widget class. The main function needs no changes:
class Widget : public QWidget
{
Q_OBJECT
int idx=0;
QTimer timer;
QPainterPath path;
QRect boundingRect;
public:
explicit Widget(QWidget *parent=0);
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
QStringList list;
float x=0;
QPointF aa;
public slots:
void changeT(){update(boundingRect);}
};
Widget::Widget(QWidget *parent) : QWidget(parent),aa(0,0)
{
connect(&timer,SIGNAL(timeout()),this,SLOT(changeT()));
timer.start(25);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin(this);
painter.setPen(QPen(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap));
path.moveTo(aa);
boundingRect.setTopLeft(QPoint(x,0));
boundingRect.setSize(QSize(30*0.25,500));
if(idx+25>list.size())
idx=0;
for(int i=idx; i<idx+25 ; i++)
{
const float y=list.at(i).toInt();
QPointF bb(x, y);
x+=0.25;
if(x>750)
{
qDebug()<<"hi:" <<"y"<<y;
x=0;
path = QPainterPath();
path.moveTo(x,y);
aa.setX(x);
aa.setY(y);
bb.setX(x);
}
path.quadTo(aa,bb);
aa=bb;
}
idx+=25;
painter.drawPath(path);
QWidget::paintEvent(event);
painter.end();
}
Upvotes: 2