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.
在一个QGraphicsScene中,我有一个背景设置,上面有几个QGraphicsItems。这些图形项目是任意形状的。我想再做一个QGraphicsItem,也就是一个圆圈,当放置在这些东西上面的时候,它会显示出这个圆圈的背景,而不是填充颜色。
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.
这就像是在photoshop中有一个多层的背景。然后,使用圆形选框工具删除背景顶部的所有图层,以显示圆圈内的背景。
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.
或者,另一种方法是设置一个不透明度设置,但是这种不透明度会直接影响到它下面的项目(但只有在椭圆中)才能显示背景。
1 个解决方案
#1
7
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.
以下可能会奏效。它基本上扩展了一个普通的QGraphicsScene,它只能将其背景呈现给任何QPainter。然后,你的“cut out”图形项目只是将场景背景渲染到其他项目之上。为了使其工作,cut out项必须具有最高的z值。
#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();
}
#1
7
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.
以下可能会奏效。它基本上扩展了一个普通的QGraphicsScene,它只能将其背景呈现给任何QPainter。然后,你的“cut out”图形项目只是将场景背景渲染到其他项目之上。为了使其工作,cut out项必须具有最高的z值。
#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();
}