Search code examples
c++qtc++11qt5qgraphicsitem

How can I set the display range of a QGraphicItemGroup?


I have a QGraphicsItemGroup aggregating several child items, and I want to show only part of the group.(not the numbers of child items, area). Just like the image here.

Image is here!

I want to show the display area.

To do that, I have tried the override the QGraphicsItemGroup::boundingRect(). However, nothing have happened. And i find this in QT docs, maybe this is the reason why doesn't work.

The boundingRect() function of QGraphicsItemGroup returns the bounding rectangle of all items in the item group.

Also, I know I can change the size of QGraphicsView to make it work. However I put the View as CentralWidget, as I also need to display other object in the View, I can not change the size of the View.

How can I set the display range of a QGraphicItemGroup?


Solution

  • To perform this task we can overwrite shape() by returning a QPainterPath that defines the visible region, so that it spreads to its children we enable the flag ItemClipsChildrenToShape:

    class GraphicsItemGroup: public QGraphicsItemGroup{
    public:
        GraphicsItemGroup(QGraphicsItem * parent = 0):QGraphicsItemGroup(parent){
            setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
        }
        QPainterPath shape() const
        {
            if(mShape.isEmpty())
                return QGraphicsItemGroup::shape();
            return mShape;
        }
        void setShape(const QPainterPath &shape){
            mShape = shape;
            update();
        }
    
    private:
        QPainterPath mShape;
    };
    

    Example:

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget w;
        w.setLayout(new QVBoxLayout);
    
        QGraphicsView view;
        QPushButton button("click me");
    
        w.layout()->addWidget(&view);
        w.layout()->addWidget(&button);
    
        view.setScene(new QGraphicsScene);
        GraphicsItemGroup group;
        view.scene()->addItem(&group);
        auto ellipse = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
        ellipse->setBrush(Qt::red);
        auto rect = new QGraphicsRectItem(QRect(150, 150, 100, 100));
        rect->setBrush(Qt::blue);
        group.addToGroup(ellipse);
        group.addToGroup(rect);
    
        QObject::connect(&button, &QPushButton::clicked, [&group](){
            QPainterPath shape;
            if(group.shape().boundingRect() == group.boundingRect()){
                shape.addRect(0, 50, 250, 150);
            }
            group.setShape(shape);
        });
    
        w.show();
        return a.exec();
    }
    

    Output:

    enter image description here

    enter image description here

    The complete example can be found in the following link.