Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a QGraphicsItem show the background in a QGraphicsScene?

In a QGraphicsScene, I have a background set with a few QGraphicsItems on top of it. These graphics items are of arbitrary shape. I'd like to make another QGraphicsItem, i.e. a circle, which when placed over these items will essentially show the background within this circle, instead of being filled with a color.

It would sort of be like having a background with multiple layers on top of it in photoshop. Then, using a circular marquee tool to delete all the layers on top of the background to show the background within the circle.

Or, another way to view it could be to have an opacity set, but this opacity affects items directly underneath it (but only within the ellipse) to show the background.

like image 404
JustinBlaber Avatar asked Jun 15 '12 17:06

JustinBlaber


1 Answers

The following might work. It basically extends a normal QGraphicsScene with the ability to only render its background to any QPainter. Then, your "cut out" graphics item just renders the scene background over top of the other items. For this to work, the cut out item would have to have the highest Z-value.

screen shot

#include <QtGui>

class BackgroundDrawingScene : public QGraphicsScene {
public:
  explicit BackgroundDrawingScene() : QGraphicsScene() {}
  void renderBackground(QPainter *painter,
                        const QRectF &source,
                        const QRectF &target) {
    painter->save();
    painter->setWorldTransform(
          QTransform::fromTranslate(target.left() - source.left(),
                                    target.top() - source.top()),
          true);
    QGraphicsScene::drawBackground(painter, source);
    painter->restore();
  }
};

class CutOutGraphicsItem : public QGraphicsEllipseItem {
public:
  explicit CutOutGraphicsItem(const QRectF &rect)
    : QGraphicsEllipseItem(rect) {
    setFlag(QGraphicsItem::ItemIsMovable);
  }
protected:
  void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
    BackgroundDrawingScene *bgscene =
        dynamic_cast<BackgroundDrawingScene*>(scene());
    if (!bgscene) {
      return;
    }

    painter->setClipPath(shape());
    bgscene->renderBackground(painter,
                              mapToScene(boundingRect()).boundingRect(),
                              boundingRect());
  }
};


int main(int argc, char **argv) {
  QApplication app(argc, argv);

  BackgroundDrawingScene scene;
  QRadialGradient gradient(0, 0, 10);
  gradient.setSpread(QGradient::RepeatSpread);
  scene.setBackgroundBrush(gradient);

  scene.addRect(10., 10., 100., 50., QPen(Qt::SolidLine), QBrush(Qt::red));
  scene.addItem(new CutOutGraphicsItem(QRectF(20., 20., 20., 20.)));

  QGraphicsView view(&scene);
  view.show();

  return app.exec();
}
like image 80
Dave Mateer Avatar answered Sep 27 '22 19:09

Dave Mateer