In a QGraphicsScene
, I have a background set with a few QGraphicsItem
s 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.
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.
#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();
}