如何做一个QGraphicsItem显示一个QGraphicsScene的背景?

时间:2023-02-01 13:41:40

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.

在一个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值。

如何做一个QGraphicsItem显示一个QGraphicsScene的背景?

#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值。

如何做一个QGraphicsItem显示一个QGraphicsScene的背景?

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