PDA

View Full Version : How to draw a cruve with increasing data?



anson97209
9th September 2009, 05:55
Hi everyone. I have a problem of how to draw a cruve with growing data. In my application, i need to draw a curve which data is collected from AD channel. I found the "realtime_plot" example, it used the draw(from,to) method. So i use this code for reference. But in my code, it doesn't work. My code like this:
d_data->append(x, y, size);
d_curve->setRawData(d_data->x(), d_data->y(), d_data->count());
canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
d_curve->draw(d_curve->dataSize() - size, d_curve->dataSize() - 1);

used above code, the cruve desn't show, but used replot() method, the curve can display:
d_data->append(x, y, size);
d_curve->setRawData(d_data->x(), d_data->y(), d_data->count());
canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
replot();

so i want to ask , how to used draw(from,to) method? And i want to draw a curve as quickly as it can. QPaintEngine::PaintOutsidePaintEvent feathure is needed, but it is not supported by qt4, and how i can realize?

Uwe
9th September 2009, 06:43
1) Which platform are you on ?
2) Does the realtime example work ?

Uwe

anson97209
9th September 2009, 12:39
1) Which platform are you on ?
2) Does the realtime example work ?

Uwe

I use linux-2.6.13 kernel on arm9 board. Qt version is qt-core-4.3.2, and qwt is 5.20
the realtime example can work, it can show a series points, but i want to display a curve not just points, so i edit this code and and debug it, the original code is
if ( d_curve == NULL )
{
d_curve = new QwtPlotCurve("Test Curve");
d_curve->setStyle(QwtPlotCurve::NoCurve);
d_curve->setPaintAttribute(QwtPlotCurve::PaintFiltered);

const QColor &c = Qt::white;
d_curve->setSymbol(QwtSymbol(QwtSymbol::XCross,
QBrush(c), QPen(c), QSize(5, 5)) );

d_curve->attach(this);
}

and i delete "d_curve->setStyle(QwtPlotCurve::NoCurve)" and "d_curve->setSymbol(QwtSymbol(QwtSymbol::XCross, QBrush(c), QPen(c), QSize(5, 5)) )";
it can't show any points, but when i left-click the mouse in the screen , it can show the curve. other more, when i just delete "d_curve->setStyle(QwtPlotCurve::NoCurve)" sentence, it can show points but no curve and when i left-click the mouse in the screen , the cruve is also showed.
But in my code, no matter what i do , it can not show anything.

Uwe
11th September 2009, 08:04
I use linux-2.6.13 kernel on arm9 board. Qt version is qt-core-4.3.2, and qwt is 5.20

Qt has been renamed so often - I can't remember if qt-core was Qt Embedded or Qt X11. This is important as on X11 you can paint outside of paint events - while on Qt embedded ( and all platforms with the raster paint engine like Windows ) QwtPlotCurve::draw is implemented using internal dummy paint events.

Also Qt 4.3 is pretty old - better upgrade if possible.


the realtime example can work,...
Then check all the flags that are temporarily enabled in IncrementalPlot::appendData.

You could also have a look at the new spectrogram example in Qwt SVN trunk. Maybe this is closer to your use case ( but I'm not sure if it works with Qt 4.3 ).

Uwe

anson97209
11th September 2009, 13:42
Qt has been renamed so often - I can't remember if qt-core was Qt Embedded or Qt X11. This is important as on X11 you can paint outside of paint events - while on Qt embedded ( and all platforms with the raster paint engine like Windows ) QwtPlotCurve::draw is implemented using internal dummy paint events.

Also Qt 4.3 is pretty old - better upgrade if possible.

Then check all the flags that are temporarily enabled in IncrementalPlot::appendData.

You could also have a look at the new spectrogram example in Qwt SVN trunk. Maybe this is closer to your use case ( but I'm not sure if it works with Qt 4.3 ).

Uwe

Thank you for your answer, and i find something has change of the realtime plot example of the latest version of qwt. Maybe I should try to debug again to find a suitable way to solve the problem.

anson97209
15th September 2009, 10:27
In the Incrememtalplot.cpp , the orginal code is this:
void IncrementalPlot::appendData(double *x, double *y, int size)
{
if ( d_data == NULL )
d_data = new CurveData;

if ( d_curve == NULL )
{
d_curve = new QwtPlotCurve("Test Curve");
d_curve->setStyle(QwtPlotCurve::NoCurve);
d_curve->setPaintAttribute(QwtPlotCurve::PaintFiltered);

const QColor &c = Qt::white;
d_curve->setSymbol(QwtSymbol(QwtSymbol::XCross,
QBrush(c), QPen(c), QSize(5, 5)) );

d_curve->attach(this);
}

d_data->append(x, y, size);
d_curve->setRawData(d_data->x(), d_data->y(), d_data->count());
#ifdef __GNUC__
#endif

const bool cacheMode =
canvas()->testPaintAttribute(QwtPlotCanvas::PaintCached);

#if QT_VERSION >= 0x040000 && defined(Q_WS_X11)
// Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent
// works on X11. This has an tremendous effect on the performance..

canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);
#endif

canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
d_curve->draw(d_curve->dataSize() - size, d_curve->dataSize() - 1);
canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, cacheMode);

#if QT_VERSION >= 0x040000 && defined(Q_WS_X11)
canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, false);
#endif
}

and I delete all the flag, and the code like this:

void IncrementalPlot::appendData(double *x, double *y, int size)
{
if ( d_data == NULL )
d_data = new CurveData;

if ( d_curve == NULL )
{
d_curve = new QwtPlotCurve("Test Curve");
d_curve->setStyle(QwtPlotCurve::NoCurve);
d_curve->setPaintAttribute(QwtPlotCurve::PaintFiltered);

const QColor &c = Qt::white;
d_curve->setSymbol(QwtSymbol(QwtSymbol::XCross,
QBrush(c), QPen(c), QSize(5, 5)) );

d_curve->attach(this);
}

d_data->append(x, y, size);
d_curve->setRawData(d_data->x(), d_data->y(), d_data->count());

canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
d_curve->draw(d_curve->dataSize() - size, d_curve->dataSize() - 1);
canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, cacheMode);

}
the example also can work. But in my own code , it cannot show anything except using the replot() method. I guess other files (such as Randomplot.cpp) impacted the plot?

anson97209
23rd September 2009, 03:52
I have find the problem. when I add zoomer class in my code, use draw() method can work. But I have another two problems:
1 the points can display in the realtime, but the curve can not display unless I left-clicked the mouse in the canvas.
2 when I enble the Qt::WA_PaintOutsidePaintEvent and disable QwtPlotCanvas::PaintCached, it can plot very fast, but it will print the debug information
"QWidget::paintEngine:should no nolonger be called"
"QPainter:begin:Paint device returned engine == 0, type:1"
"QPainter::setClipping:Painter not active, state will be reset by begin"
"QPainter::save:Painter not active"
"QPainter::store:Unbalanced save/restore"

Uwe
23rd September 2009, 06:40
Qwt 5.2.0 doesn't call any QWidget::paintEngine() anymore. If you are really using it try to find out, where QWidget::paintEngine() is called ( f.e setting a breakpoint in qWarning() ).

Uwe

anson97209
23rd September 2009, 12:43
Thank you!
I want to ask the frist question, why the points can display in the realtime, but the curve can't.

Uwe
24th September 2009, 07:09
If you want to see connecting lines between the points you need to pass the start and endpoint for these lines - not only a single point. So if you want to paint point by point you always have to add the previous point to QwtPlotCurve::draw().

Uwe

anson97209
26th September 2009, 13:21
Uwe, Thank you very much, you really help me a lot!
Follow you tips, I just changed the code like that
d_curve->draw(d_curve->dataSize() - 2, d_curve->dataSize() - 1);
and the curve can display in the realtime.
But it must disable Qt::WA_PaintOutsidePaintEvent. As a result, it plot very slowly, Can i have a method to let it plot faster ?

Uwe
27th September 2009, 09:03
But it must disable Qt::WA_PaintOutsidePaintEvent.
No, Qt::WA_PaintOutsidePaintEvent has nothing to do with what you are painting. But even if you have Qt::WA_PaintOutsidePaintEvent disabled you shouldn't run into the slow path, where the complete plot is repainted.

Uwe

anson97209
27th September 2009, 16:19
No, Qt::WA_PaintOutsidePaintEvent has nothing to do with what you are painting. But even if you have Qt::WA_PaintOutsidePaintEvent disabled you shouldn't run into the slow path, where the complete plot is repainted.

Uwe

I am sorry, I didn't understand what is slow path mean? Is it mean that if I want to display the curve, the complete curve will be repainted?
In my case:
1. when I enable Qt::WA_PaintOutsidePaintEvent , it plot faster, but it can not display the curve in the realtime unless I left-click mouse on the canvas.
2. when I disable Qt::WA_PaintOutsidePaintEvent , it plot slower, but it can display the curve in the realtime.
3. when I use replot() method, it plot slowest.
How should I do, if I want to display the curve in the realtime and it can plot faster?

Uwe
28th September 2009, 07:21
Is it mean that if I want to display the curve, the complete curve will be repainted?
There are 3 different ways how drawCurve might paint the curve. It depends on the abilities of your environment and how you configured the operation. On X11 you can have the fastest path on the Mac you will run into full repaints of the plot ( not only the curve ).



1. when I enable Qt::WA_PaintOutsidePaintEvent , it plot faster, but it can not display the curve in the realtime unless I left-click mouse on the canvas.
Painting incrementally doesn't depend on what is painted. You wrote, that the realtime example works - so it's obviously a problem in your application code.

Uwe

anson97209
30th September 2009, 05:35
Painting incrementally doesn't depend on what is painted. You wrote, that the realtime example works - so it's obviously a problem in your application code.

Uwe

when I enable Qt::WA_PaintOutsidePaintEvent, it will run faster, but it can't display anything unless I left-clicked mouse in the canvas, it is the same in the realtime_plot example not only just in my application code.

Uwe
30th September 2009, 07:08
when I enable Qt::WA_PaintOutsidePaintEvent, it will run faster, but it can't display anything unless I left-clicked mouse in the canvas,
No surprise, when it doesn't paint anything.

... it is the same in the realtime_plot example not only just in my application code.
I explicitely asked if it is working ...

I checked the example with Qt 4.3 on X11 with success - so I guess you are running Qt Embedded ( I also asked you which Qt you are using ... ). On Qt Embedded Qt::WA_PaintOutsidePaintEvent is not supported and of course nothing will be painted ( clicking in the canvas triggers a repaint ).

The strategy on platforms, where the raster paint engine is used, is that each drawCurve posts a dummy event and paints inside the paint event. You have the penalty of posting/processing the paint event, but you don't need to paint anything beside the additional points. There is no way to get around this limitation of Qt4 ( Qt3 should be faster ).

You didn't write how many points you want to paint in which time and I have no idea how fast your arm board is. But with the realtime example you can try to find out what is possible.

One more hint: fixing performance issues of the raster paint engine was one of the main features of Qt 4.5. If painting is too slow you could try to upgrade from Qt 4.3 ( AFAIR you might have something about 20-30%).

Uwe

anson97209
4th October 2009, 02:25
Thank you very much!

sumit@sofomo.co.in
30th November 2009, 14:35
Thank you very much!
Hi anson97209,

I'm also trying to plot running data and have referred curveplot1, curveplot2, realtimeplot and so on example but was unable to make it up to the mark.
Can you upload your complete plotting code or mail me to sumit@sofomo.co.in?

Thank You.

Regards,
Sumit