PDA

View Full Version : Graphics View Queries



linuxdev
23rd December 2008, 14:11
Hi,

Trying to understand the basics of Graphics View,
I have written a simple code snippet to do so,


int main(int argc, char *argv[])
{
qDebug("In Main");
QApplication a(argc, argv);

QGraphicsScene *scene = new QGraphicsScene();

QGraphicsView *viewGv = new QGraphicsView();
viewGv->setScene(scene);

scene->setSceneRect(QRectF(0, 0 , 10, 10));
QGraphicsTextItem * item1 = scene->addText("Hello World");

scene->setBackgroundBrush(Qt::blue);
QPen pen1;
pen1.setColor(Qt::red);
scene->addLine(0,0, 10,10, pen1);

viewGv->show();
return a.exec();

}

Here i have set the scene rect as (0,0,10,10), and have set its background to blue color.
When i run the application a small window appears as intended when i maximise it the entire window is filled with blue color....:confused:

I expected only the area (0,0,10,10) which represents the scene to be filled as blue.. :(
whats happening here can anyone help me understand this???

caduel
23rd December 2008, 15:16
The "sceneRect" is the coordinate space inside the QGraphicsView.
It has nothing to do with pixels on the screen:
The whole available arae is mapped to the scene rect. Thus you can draw in the view without having to care about your widgets size.

If you want to set the size of the widget itself, you may do that (with any widget) by calling QWidget::resize().

HTH

linuxdev
23rd December 2008, 15:43
Hi,

Thanks for the reply ...
But i am new to Graphics View, so can you give me enlighten me, about the basics of these mappings ?

i.e. if setSceneRect is related to View then why do i need to say "scene"->setSceneRect ?

where is pixel in this mapping?
what do you mean , when you said , "The whole available area"?

"Thus you can draw in the view without having to care about your widgets size."
I thought view is a widget as it derives from that?
I am confused can you pls help me out?

caduel
23rd December 2008, 17:27
The view as a widget has some size (width,height).
If you resize the widget this size changes.
In order to make drawing easier, item coordinates are in a separate coordinate system (see graphicsview, look for "coordinate system"). This coordinate system in set with setSceneRect. You say: "let's pretend the drawing area to be rect (0,0)-(10,10)."
So, when you draw a line from (0,0) to (10,10) these coordinates are mapped to the widget's coordinates: the line is drawn (diag.) across the whole widget.

If this was not the case, then you would have to calculate the positions (taking into account your view's size). So this decoupling -amongst other things- makes your life easier: you know that the middle of the view is at the (scene coord) 5.
Moreover, it would not be possible to display the same scene in different views (as the views might have different sizes).

HTH

linuxdev
24th December 2008, 07:05
When i set the scene rect as (0,0,10,10) the line and text appear in the middle of my view, but if i set it to (0,0,1000,1000) same appears at the top left corner of the view, whats going on here?

wysota
30th December 2008, 11:11
If the scene size is smaller than the view size, by default the view displays the scene in the middle of the viewport (you can change that behaviour by modifying the scene alignment property of the view). When the scene is larger (or equal) than the view then this rule doesn't apply, the scene will always cover the whole view so the alignment is meaningless.

linuxdev
5th January 2009, 06:43
Thanks for the reply.

I have enhanced my small application to do much more work.

Now it does the following:

1. it has a background which are nothing but six concentric circles (shown always)

2. An elliptical item is drawn at the outermost position and its position is moved every 10msec around the ellipse in steps of 10deg.

3. I have Zoom feature around the center, also panning is done through scroll option provided by QGraphicsView.

4. An option to remove the Pan.

I have severe time constraints to my application and i need to draw somewhere around 500 items at a time with worst case refresh rate of 30msec.

When i try to pan around using mouse , the refresh rate is dropped...

Can someone please have a look at the source and let me know if there is any serious design flaw? so that it doesnt carry on further in my code...

wysota
5th January 2009, 09:43
1. Get rid of updateCapPos(). Use QGraphicsScene::advance() or QGraphicsItemAnimation instead.

2. Disable hover for MyItem and GvHmiBgItem, you're not using it anyway so it's a plain waste of processing power.

3. Don't disable indexing in the scene unless you know you won't need it, you have only a few items so updating the index yields practically no overhead.

4. If you don't use mouse events with the scene and items, call QGraphicsView::setInteractive(false).

This should get you some speedup. I'd also suggest disabling ItemIgnoresTransformations and rely on the scene to recalulate proper item sizes, currently your implementation is incorrect as the scene doesn't see boundingRect() changes of your items, so it uses a too large boundingRect and redraws your items much too often.

linuxdev
6th January 2009, 07:39
Thanks for the response :)
But i need to Ignore the Transformation for some items as they are required to retain the size independent of zoom level.

I didnt get your point, when you said "currently your implementation is incorrect as the scene doesn't see boundingRect() changes of your items, so it uses a too large boundingRect and redraws your items much too often".

Which item are you referring to ? The background item or the elliptical item?

I have also observing a strange behaviour,

When i set the update interval as 1msec, and run my app, the elllipse moves very fast but if i dont interact with the scene and leave the application alone, i dont see the movement of the item.
what could be the problem?

wysota
6th January 2009, 09:30
But i need to Ignore the Transformation for some items as they are required to retain the size independent of zoom level.
That's not what your code does.


I didnt get your point, when you said "currently your implementation is incorrect as the scene doesn't see boundingRect() changes of your items, so it uses a too large boundingRect and redraws your items much too often".
Your boundingRect() implementation returns a variable size but you never inform graphics view that this size has actually changed so it always uses the bounding rect that was returned the first time and this will slow down painting if the rect is bigger than you actually need it to be.


Which item are you referring to ? The background item or the elliptical item?
Both, as far as I remember.


When i set the update interval as 1msec, and run my app, the elllipse moves very fast but if i dont interact with the scene and leave the application alone, i dont see the movement of the item.
what could be the problem?

I'd say that's a combined problem resulting from what I described earlier. Your usecase is very simple and you make it way too complicated.

linuxdev
7th January 2009, 06:29
That's not what your code does.

"i need to Ignore the Transformation for some items as they are required to retain the size independent of zoom level."
for this i have just set the flag "item3->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);"
This should satisfy my requirement right? what's my code doing, where am i going wrong?




Both, as far as I remember.
I have used Standard EllipseItem of the Framework, this should take care of the issue automatically right?
I think i need to call "prepareGeometryChange();" for custom item , should i do this in the Resize Event?





Your usecase is very simple and you make it way too complicated.
I guess there is a design flaw somewhere , how can it be simplified ? can you help me rectify my attached code ?

wysota
7th January 2009, 09:40
What exactly is your application meant to do? I ran the code you provided but I don't see much :)

linuxdev
7th January 2009, 10:08
Hmm :)

I didnt want to go deep into it, now that you have asked for, i think you would have to read completely ;)

My application is a Radar Display System,
I receive data from radar , through network which represent aircrafts in space.
The data received is to be plotted on to the display. the concentric circle represent the PPI view.
Origin represents the radar and rings are mapped to 10Km , 20 and so on ....

a. Application receives data from Network continuously.
b. This data has to be processed and then drawn on to the scene.
c. There can be as many as 600 data items for every 4 secs or even lesser interval.
d. data which is old by one interval should be changed to a different color and that those which are old by two intervals should be deleted/erased from the display. (aircraft gone away)

I have done bulk of my Coding in QPainter, its not living to expected performance, now i am planning to do the same in GraphicsView. (Following the way showed by you :))

The Application i have done now , is to test whether GraphicsView Framework will do my job at much better performance boost.
For that,
a. I have not added the network part in this miniature app.
b. Instead to test performance , i am drawing only one data at an interval of 10msec. (Planning to put 500 more items)

Will this workout ?
Should i still need to use QThread for Network or its fine with the GraphicsView Framework.

The radar is quite fast , it rotates at 24 Rpm. Pumping data upto 600 data in one rotation.
I have to display them efficiently, giving much better User Response. (As he will do a lot of other things)

This is my Story, hope to receive some help so that i can make a movie :)

wysota
7th January 2009, 10:44
In that case I would draw the crosshair using drawBackground() or drawForeground() and the aircrafts and other potential objects using items of the graphics view. I would probably not use scaling even if you want to have different zoom levels, as most objects would have to ignore transformations anyway, so it might be easier to move them around instead of scaling - losing transformations altogether would make things much faster. Bare QPainter is fine too but you'd have to do some caching to avoid recalculating everything.