Layers on QGraphicsView?
Asked Answered
B

3

9

Hi I'm making an application that pulls data from a WFS and then displays those layers of data on a QGraphicsView on a widget. At the moment all layers are rendered and added to the same view meaning if I want to turn a layer of it means re-rendering all of it except that layer.

At the moment im adding a QGraphicsScene with Ellipse Items and Polygon Items added to it, to the graphics scene. I'm wondering if its possible to add multiple scenes to a graphics view or layers to a scene or something that would allow me to just hide/show certain points/polygons from a check box or something that simply hides a layer?

I know this is kind of vague but I'd appreciate any help.

Thanks.

Biflagellate answered 6/8, 2013 at 8:6 Comment(0)
H
10

Another way to go is QGraphicsItemGroup

Something like:

// Group all selected items together
QGraphicsItemGroup *group = scene->createItemGroup(scene->selecteditems());
...
// Destroy the group, and delete the group item
scene->destroyItemGroup(group);

So you can treat group as a layer and since group is also QGraphicsItem have all features like show()/hide() etc.

UPDATE: Changing Z-val for a group will allow you to implement things like 'move layer to top/bottom'

Hooded answered 6/8, 2013 at 9:58 Comment(3)
Thanks for the answers, im gunna spend a bit of time trying each theory out and then choose an answer based on what works best, upvoting all cheers for the help!Biflagellate
went with this in the end because it worked best for what i needed, not exactly how i did it from your code but pretty much, i also used group->show and group->hide to show/hide the polygons/points from the graphics view works nicely and no unnecessary amount of codeBiflagellate
In case the QGraphicsItem(s) in the QGraphicsItemGroup should be moveable then: You need to call QGraphicsItemGroup::setHandlesChildEvents(false). This stops the QGraphicsItemGroup trying to handle the event, and lets the child QGraphicsItems handle them instead.Heuser
H
14

You only need one QGraphicsScene, but the key here is that all QGraphicsItems and QGraphicsObjects can be parented.

If you create a single QGraphicsItem or QGraphicsObject as a parent object, it doesn't need to draw anything, but can be used as the root for a layer's items.

Therefore, subclass from QGraphicsItem to create a QGraphicsItemLayer class that doesn't render anything and add all the ellipses, polygons etc that are required in the same layer as children of that QGraphicsItemLayer.

When you want to hide a layer, just hide the parent QGraphicsItemLayer object and all its children will be hidden too.

-------- Edited --------------

Inherit from QGraphicsItem: -

class QGraphicsItemLayer : public QGraphicsItem
{
    public:
        virtual QRectF boundingRect()
        {
            return QRectF(0,0,0,0);
        }

        virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
        {
        }
};

Create a layer item:

QGraphicsItemLayer* pLayer = new QGraphicsItemLayer;

Add the objects you want to the layer, note that pLayer is passed as the parent

QGraphicsEllipseItem = new QGraphicsEllipseItem(pLayer);

Assuming you've created the QGraphicsScene with a pointer to it called pScene: -

pScene->addItem(pLayer);

Then when you want to hide the layer

pLayer->hide();

Or display the layer: -

pLayer->show();
Hengelo answered 6/8, 2013 at 8:53 Comment(6)
thanks for the answer but just saying do a subclass that works doesnt really help, that could answer most questions, its the doing this that i need help with ...Biflagellate
Why did this answer receive a downvote? It answers the question just fine. AngryDuck, just subclass QGraphicsItem and provide empty implementations of boundingRect() and paint().Te
@StefanMajewsky, thanks for the support. There are many cowards on SO that just downvote with no explanation. If we could see who they were, it would be a better place, in my opinion.Hengelo
As @StefanMajewsky states, there's really very little to it, all you need is the object to be a parent, so inherit from QGraphicsItem (or QGraphicsObject if you want signal and slots) and with the empty implementations you can then add it to the scene and add the children.Hengelo
Will additem(parent) automaticly add its children?Snobbery
@dani, yes - that's what the documentation states!Hengelo
H
10

Another way to go is QGraphicsItemGroup

Something like:

// Group all selected items together
QGraphicsItemGroup *group = scene->createItemGroup(scene->selecteditems());
...
// Destroy the group, and delete the group item
scene->destroyItemGroup(group);

So you can treat group as a layer and since group is also QGraphicsItem have all features like show()/hide() etc.

UPDATE: Changing Z-val for a group will allow you to implement things like 'move layer to top/bottom'

Hooded answered 6/8, 2013 at 9:58 Comment(3)
Thanks for the answers, im gunna spend a bit of time trying each theory out and then choose an answer based on what works best, upvoting all cheers for the help!Biflagellate
went with this in the end because it worked best for what i needed, not exactly how i did it from your code but pretty much, i also used group->show and group->hide to show/hide the polygons/points from the graphics view works nicely and no unnecessary amount of codeBiflagellate
In case the QGraphicsItem(s) in the QGraphicsItemGroup should be moveable then: You need to call QGraphicsItemGroup::setHandlesChildEvents(false). This stops the QGraphicsItemGroup trying to handle the event, and lets the child QGraphicsItems handle them instead.Heuser
B
2

I think you could try to partition your objects according to z value: see setZValue. Then introduce a mapping between layer id and indexing. A simple QStringList could do.

Of course, there are many details and variations that a practical solution will need to account for.

Butyraceous answered 6/8, 2013 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.