8

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.

Anurag Singh
  • 492
  • 6
  • 16
AngryDuck
  • 4,358
  • 13
  • 57
  • 91

3 Answers3

11

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();
Angie Quijano
  • 4,167
  • 3
  • 25
  • 30
TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • 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 ... – AngryDuck Aug 06 '13 at 09:00
  • 2
    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()`. – Stefan Majewsky Aug 06 '13 at 09:24
  • 1
    @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. – TheDarkKnight Aug 06 '13 at 09:39
  • 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. – TheDarkKnight Aug 06 '13 at 09:41
  • Will additem(parent) automaticly add its children? – dani May 15 '16 at 06:08
  • @dani, yes - that's what the [documentation](http://doc.qt.io/qt-5/qgraphicsscene.html#addItem) states! – TheDarkKnight May 16 '16 at 08:09
9

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'

Angie Quijano
  • 4,167
  • 3
  • 25
  • 30
evilruff
  • 3,947
  • 1
  • 15
  • 27
  • 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! – AngryDuck Aug 06 '13 at 10:31
  • 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 code – AngryDuck Aug 06 '13 at 11:08
  • 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. – qknight Sep 23 '15 at 17:53
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.

CapelliC
  • 59,646
  • 5
  • 47
  • 90