PDA

View Full Version : QPainter update()



csvivek
21st March 2008, 08:33
Hello There,

i am developing an application to display 2D objects on screen with Qt4.2.2

i am using QPainter class :confused:to show objects on the screen.
The Requirement is to show small ellipse like objects. The Total number of objects is 500 and all these should be updated on the screen in micro seconds.

i find the QPainter Class taking time of about 200 milliseconds on average to update atleast 300 plots.i use update() method to avoid flicker.

should i need to use repaint class to update the screen()?if yes then how shall i avoid flicker.

is there any other method other than repaint() or update() to display the objects?
should i need to use QPainter Class or is there any other option to update the screen in microseconds?

Thanks in Advance...:D


QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1);


void AnalogClock::paintEvent(QPaintEvent *)
{

int side = qMin(width(), height());
static int i = 0, j =0;
static int flag = 1;
int diameter;
if(j<420)
{
j++;
}
else
{
printf("\nThe cleint exited");
exit(0);
}
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
side =qMin(width(),height() );
painter.translate(side / 2, side / 2);

painter.drawRect(-side/2,-side/2,side,side);

painter.fillRect(QRect(-side/2,-side/2,side,side),QBrush(Qt::black));

static const QPointF points[4] = {
QPointF(0,-side/2),
QPointF(0,side/2),
QPointF(-side/2,0),
QPointF(side/2,0)
};
painter.setPen(QPen(Qt::green,1,Qt::DotLine));
painter.drawLines(points,2);
painter.setPen(QPen(Qt::green));
painter.drawText(420,0,"60.0");
painter.drawText(350,0,"50.0");
painter.drawText(280,0,"40.0");
painter.drawText(210,0,"30.0");
painter.drawText(140,0,"20.0");
painter.drawText(70,0,"10.0");
painter.save();
painter.restore();
painter.setPen(QPen(Qt::green));
for (diameter = 140; diameter<=840; diameter+=140)
{ painter.drawEllipse(QRect(-diameter / 2, -diameter / 2,
diameter, diameter));
}
painter.setPen(QPen(Qt::black));
for(i = 1; i <= 420; i= i+5)
{
if(flag == 1)
{
painter.setBrush(QBrush(Qt::red,Qt::SolidPattern)) ;
flag = 0;
}
else
{
painter.setBrush(QBrush(Qt::blue,Qt::SolidPattern) );
flag = 1;
}
painter.drawEllipse(QRect(i,j,10,10));
painter.drawEllipse(QRect(-i,j,10,10));
painter.drawEllipse(QRect(i,-j,10,10));
painter.drawEllipse(QRect(-i,-j,10,10));
}
painter.end();
}

Manohar
21st March 2008, 08:42
Instead of painting in widget ..........
try to paint in Qpixmap .....
then use bitBlt() function to decrease flickerring

wysota
21st March 2008, 09:55
and all these should be updated on the screen in micro seconds.
Why? Be aware that if you have a 2GHz CPU, it can execute not more (which in most cases means "less") than 2G machine instructions per second. If you want to update contents within microseconds (10e-6) bounds, you are leaving only a few thousand cycles for such an update and all other operations performed by the machine including context switching (that by itself takes about 2-5 thousand cycles per switch). So there is no way you're going to update 300 plots like that.


i use update() method to avoid flicker.
No, you use update() to ask the widget to repaint itself.


should i need to use repaint class to update the screen()?if yes then how shall i avoid flicker.
What do you mean by "repaint class"?


is there any other method other than repaint() or update() to display the objects?
Simplifying things, repaint() calls paintEvent() directly and update() performs a delayed call to paintEvent(), they don't perform updates themselves. Anyway avoid using repaint() unless you know you are smarter than Qt in a particular situation. In 99% of the cases you'll be using update().


should i need to use QPainter Class or is there any other option to update the screen in microseconds?
There is no option unless you can use your GPU to render the plot and reduce the load on CPU. And certainly not using QTimer, as it operates with milisecond frequency.



QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1);
Do you really need 1000 updates per second? You wouldn't even notice subsequent changes, OpenGL or not. Human eye can see fluent motion with 16 frames per second, so if you change "1" to "50" to get 20 fps, you should get huge improvement without quality loss.


Instead of painting in widget ..........
try to paint in Qpixmap .....
then use bitBlt() function to decrease flickerring

bitBlt() is no longer used in Qt4, all widgets are by default double buffered. Besides rendering to a pixmap in that case is pointless, because the contents change very frequently, so the application would render the contents to the pixmap and then blit it to the widget only once, so it's quicker to render directly. Using a pixmap could be benefitial if the contents were static.

Cheers!

Stukfruit
21st March 2008, 11:45
Use QGraphicsView instead, this is one of the things it's meant to be used for :)

Also, OpenGL is not a magic option to speed things up (especially these kind of things), please keep that in mind.

csvivek
24th March 2008, 06:23
Hi

Thnx for the reply...

I am new to QT and have no information about QGraphicsView, i just read through the concept, i have time constraints to implemtent my requirement.

My requirement is i need to receive data from a socket, to be continuously drawn on the widget.
The socket is pumping data with the worst case speed of 1ms.

I have a thread to receive the data, after reception i copy the data into the widget's member to be drawn, then i call the update() function.

here i have two problems
1.Update requires some time to finish its job, but by this time there is a possibility of receiving new data.
here i may miss soem data from socket or painting for that set is incomplete ...

2.For the sake of optimization, its said that "Calling update() several times normally results in just one paintEvent() call." so in this case what happens to the data which is to be drawn for each update?
i.e. lets say i received 4 data which would result in calling 4 updates and ideally the widget was supposed to be redrawn 4 times.
but due to this optimization i may have only the last data read.

Can anybody suggest what needs to be done for this, i think i need to implement a buffer, but i dont know how to pass this info for PaintEvent.

Now does QGraphicsView solve my problem?

fullmetalcoder
24th March 2008, 10:42
My requirement is i need to receive data from a socket, to be continuously drawn on the widget.
Continuity is a purely mathematical concept. Software is limited by the hardware it runs on and is thus, by essence, discrete...

Now you need to make a choice :

is your plot meant to be viewed in real time by the user with no possibility to look backward? Then skip some paint events, possibly caching the data if it does not overlap.
if this is not the case store everything and render on demandAs a side note you might consider updating only the part of your widget which need to be updated.

I also just wanted to point out the QPainter vs OpenGL does not make sense since QPainter can use OpenGL... Just use a QGLWidget as a viewport and QPainter will rely on OpenGL for all its drawing operations... That's the point of this class by the way : abstracting the drawing operations.