PDA

View Full Version : Draw New data, without erasing old ones



linuxdev
12th December 2008, 17:27
Hi,

I am into the development of an app, which receives data from network, and draws circular regions 192.168.1.250 , which is defined by the data received.
I need to retain the data on the widget for some time 'x' and then change color and after some delay 'y', erase it.

I have already coded it, by retaining the old data in a buffer and redraw all the data , when a new one arrives..:o

It is consuming lot of time and its not responsive when the data rate is too high..the user has to do other operations also.

I am planning to Shift to Graphics View, (now done using QPainter)

Can some one help me out with code snipptes?

jpn
28th December 2008, 21:15
Can some one help me out with code snipptes?
It's more likely to get answers if you provide some code snippets yourself. Try at least something... :)

linuxdev
29th December 2008, 06:33
This is one function which is called inside my paintEvent.




{


if(SVL)
{

This is used to draw old data in different colors and delete them once age is reached
if(plotdetails.isEmpty() == false)
{

if(ncm_received == 1) //Data received from Tcp Socket, used to update the age
{
for(int i=0;i<plotdetails.size();i++)
{
tempplot = plotdetails.at(i);
if(tempplot.age==1)
{
tempplot.scan = 1;
}
else if(tempplot.age==2)
{
tempplot.scan = 2;
}
plotdetails.replace(i,tempplot);
}
ncm_received = 0;
}
for(int i=0;i<plotdetails.size();i++)
{
tempplot = plotdetails.at(i);

if(ncm_received == 0)
{
if(tempplot.tazimuth == 0)
{
if(tempplot.scan == 1)
{
tempplot.age=2;
plotdetails.replace(i,tempplot);
}

else if(tempplot.scan == 2)
{
tempplot.age=3;
plotdetails.replace(i,tempplot);
//plotdetails.remove(i);
}
}

if((tempplot.tazimuth >= capminutes) && (tempplot.tazimuth <= (capminutes + 2731u) )
||
(capminutes >= 62500))
{
if(tempplot.scan == 1)
{
tempplot.age=2;
plotdetails.replace(i,tempplot);
}

else if(tempplot.scan == 2)
{
tempplot.age=3;
plotdetails.replace(i,tempplot);
}

}


}


if(tempplot.age==1 && plotenabled == true)
{
painter->rotate(180 + (tempplot.tazimuth/182.047222265));
painter->drawPixmap(QRectF(-(plocntpix.width()/(2)),(((1.8 *
tempplot.trange)/1000)*(side-50)/(ppi_defaults.max_range*2))-(plocntpix.height()/(2)),plocntpix.width(),plocntpix.height()),plocntp ix,QRectF(0,0,plocntpix.width(),plocntpix.height() ));
painter->rotate(-(180 + (tempplot.tazimuth/182.047222265)));

}
else if(tempplot.age==2 && plotenabled == true && preplotenabled == true)
{
painter->rotate(180 + (tempplot.tazimuth/182.047222265));
painter->drawPixmap(QRectF(-plotgraypix.width()/(2),(((1.8 *
tempplot.trange)/1000)*(side-50)/(ppi_defaults.max_range*2))-(plotgraypix.height()/(2)),plotgraypix.width(),plotgraypix.height()),plo tgraypix,QRectF(0,0,plotgraypix.width(),plotgraypi x.height()));
painter->rotate(-(180 + (tempplot.tazimuth/182.047222265)));

}

else if(tempplot.age == 3)
{
plotdetails.remove(i);
i--;
//printf("REMOVED THE ELEMENT FROM QUEUE\n");
}

}

}

//Start drawing the plot, after receiving from the network
if(m_vplot.isEmpty() == false)
{
for(int i = 0; i<m_vplot.size();i++)
{

templot.trange = m_vplot.at(i).range;
templot.tazimuth= m_vplot.at(i).azimuth;
templot.elevation= m_vplot.at(i).elevation;
templot.tazimuthextn= m_vplot.at(i).azimuthextn;

azimthext = (templot.tazimuthextn/182.047222265);
templot.age=1;
templot.scan =0;

if(plotenabled == true)
{
plotminutes =((m_vplot.at(i)).azimuth)/182.047222265;
temp1= 180 + plotminutes;
painter->rotate(temp1);
painter->drawPixmap(QRectF(-(plocntpix.width()/(2)),(((1.8 *
m_vplot.at(i).range)/1000)*(side-50)/(ppi_defaults.max_range*2))-(plocntpix.height()/(2)),plocntpix.width(),plocntpix.height()),plocntp ix,QRectF(0,0,plocntpix.width(),plocntpix.height() ));
painter->rotate(-temp1);

if(!plotdetails.contains(templot))
{
plotdetails.append(templot);
}

painter->save();

int startAngle = 0;/*(90-15) * 16*/;
int spanAngle = 0;/*30 * 16;*/
float rangepixel = (((1.8 * m_vplot.at(i).range)/1000)*(side-50)/(ppi_defaults.max_range*2));
rangepixel = fabs(rangepixel);
QRectF rectangle(-(rangepixel), -(rangepixel), (rangepixel*2), (2*rangepixel));

painter->restore();

}
}
m_vplot.clear();
}

}
else
{
if(plotdetails.isEmpty() == false)
plotdetails.clear();

if(m_vplot.isEmpty() == false)
m_vplot.clear();
}
#endif
}



Variables of importance:
a. m_vplot: is a QVector, which has all the data received from the network, using QTcpSocket (This is cleared after its used).
b. plotdetails : is a QVector , which acts as a buffer to hold the data to be drawn and retained on the widget.

Flow of Code:
The data received from Tcp is drawn immediately and also added to the buffer.
In buffer i use variable age to maintain the age of the data, if it changes then i change the color, or delete from the buffer, so that its no longer drawn.

Looking forward to your response.

linuxdev
31st December 2008, 07:19
I think i have tried at least something for someone to reply ;)

jpn
31st December 2008, 08:01
Why don't you use a pixmap as a drawing buffer? Whenever new data arrives, you'd draw that on the pixmap and then you'd dump the pixmap on the screen. That way you wouldn't have to always redraw everything...

linuxdev
5th January 2009, 06:29
This seems to be a good option, but i even need to remove some of the data, once it has reached a certain time.

i.e.
My requirement is :

1. I receeive the data , then i draw an Ellipse at position (100, 100) in my Pixmap.
2. after say 3 seconds i have to change the color of an item(ellipse in this case) at the same position (100,100) to grey.
3. and then again after 3 seconds i need to erase it.

How can i do these things if i use a Pixmap?

can you please help me out?

linuxdev
5th January 2009, 06:44
I also have a background, which is having an Image , so while trying to erase the items say at (100,100) it should not erase the background :D

wysota
5th January 2009, 23:30
With all those requirements I'm afraid you'll have to draw everything each time. Simply store your previous steps in a buffer, remove stale data from buffer, insert new data into the buffer and then paint everything that's in the buffer. Just like the Command pattern.

linuxdev
6th January 2009, 07:25
Hmm :(, i cant do that as its a real time application, and there should be no time delay, if i dont see the item on my screen at the right time i am dead :).

I have this idea,
a. Will draw an ellipse (which always fits within a rect of width and height as 4) in blue color.
b. Now when its the time to change color, i can redraw the ellipse in different color.
c. Now its time for it to erase, then i can fill the rect (width and height as 4) at the required position with black color. (I hope this shouldnt erase my background image as its a seperate Pixmap)

Now my concern in this case would be,
Two ellipse may overlap ,

so i need some sort of algorithm in Qt to detect this overlap and carefully do the changing of color or erasing of already drawn items.

I might to be going too optimistic , is it possible? can you show me the way?

wysota
6th January 2009, 11:11
Hmm :(, i cant do that as its a real time application,
Do you have a real-time OS? If not, forget about real time, focus on "fastest possible".


and there should be no time delay, if i dont see the item on my screen at the right time i am dead :).
You will see everything at the right time unless you are drawing zillions of pieces of data at once.


I have this idea,
a. Will draw an ellipse (which always fits within a rect of width and height as 4) in blue color.
b. Now when its the time to change color, i can redraw the ellipse in different color.
c. Now its time for it to erase, then i can fill the rect (width and height as 4) at the required position with black color. (I hope this shouldnt erase my background image as its a seperate Pixmap)
At each time you will have to redraw everything regardless of what you do. Even if you use a pixmap buffer, you will have to redraw the whole pixmap. From what I see you are always drawing a single entity (ellipse or no ellipse) so speed should not be an issue here.



so i need some sort of algorithm in Qt to detect this overlap and carefully do the changing of color or erasing of already drawn items.
This is more complicated that using QGraphicsView which I advise you to look at.

linuxdev
7th January 2009, 06:45
You will see everything at the right time unless you are drawing zillions of pieces of data at once.

I am seeing them at once.
But my app response is low,
a. data which is in the buffer is read from a network at the same rate (500 items in 4 sec)
b. as and when i read single data into buffer i call update() on my widget to schedule a paint.
c. In the PaintEvent, i draw all the previous data (if any) and the current received data.


May be this is making my UI less responsive? I need to make it as a Thread but the QTCpSocket is used in many classes to send data, as far i understand the networking stuff should be limited to one QThread. So i think its little tricky , is there any example which does implement Network read and write as QThread?




From what I see you are always drawing a single entity (ellipse or no ellipse) so speed should not be an issue here.
My drawing is in a loop running till buffer size. It needs to draw 500 items in 4 secs (worst case), every time i receive a new data i have to redraw everything from the buffer along with the new data.




This is more complicated that using QGraphicsView which I advise you to look at.

Even if i move to GraphicsView, reading from Network shouldnt be a Bottle Neck to me , should i use a Thread?

I am slowing moving to GraphicsView, but i have already developed much of code with QPainter, and trying hard to get best out of it.

I have attached two major files of my source
1. circlewidget.cpp : One that handles drawing
2. HmiGenric.cpp : This handles networking. (In this sendmsg() is called from different objects to send data) , this shouldnt be a hurdle to make this class as a Thread i guess.

Can you help me out?

wysota
7th January 2009, 09:34
b. as and when i read single data into buffer i call update() on my widget to schedule a paint.
This is wrong. Schedule a repaint at some specified interval (like 10 or 20 times a seconds). Your eyes wouldn't notice faster redraws anyway.


I need to make it as a Thread but the QTCpSocket is used in many classes to send data, as far i understand the networking stuff should be limited to one QThread. So i think its little tricky , is there any example which does implement Network read and write as QThread?
Using QThread will only slow down your application as you'll need to synchronize those threads all the time.