如何让QGraphicsItem显示QGraphicsScene中的背景?

时间:2012-06-15 17:06:03

标签: qt qgraphicsitem qgraphicsscene

QGraphicsScene中,我有一个背景设置,其上面有几个QGraphicsItem。这些图形项具有任意形状。我想制作另一个QGraphicsItem,即一个圆圈,当放置在这些项目上时,它将基本上显示此圆圈内的背景,而不是填充颜色。

它有点像在photoshop中有一个多层的背景。然后,使用圆形选框工具删除背景顶部的所有图层以显示圆圈内的背景。

或者,查看它的另一种方法可能是设置不透明度,但此不透明度会直接影响其下方的项目(但仅限于椭圆内)以显示背景。

1 个答案:

答案 0 :(得分:7)

以下可能有效。它基本上扩展了普通QGraphicsScene,只能将其背景呈现给任何QPainter。然后,您的“剪切”图形项目只会将场景背景渲染到其他项目的顶部。为此,切出的项目必须具有最高的Z值。

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();
}