A.Ajorian
A.Ajorian

Reputation: 159

ECG Signal Drawer using Qt

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

Answers (1)

A.Ajorian
A.Ajorian

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

Related Questions