2012-06-15 55 views
7

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

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

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

+1

的程序,我用所谓的实时绘制所谓的“推背”对象概括这一点。相当有用,你可以考虑使用类似的泛化:http://www.mediachance.com/realdraw/help/index.html?pushback.htm – HostileFork

回答

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

Dave,非常感谢。这段代码非常有趣。你可以修改它,让椭圆移动?在发送之前,我使用'setFlag(QGraphicsItem :: ItemIsMovable,true)和setFlag(QGraphicsItem :: ITemIsSelectable,true)'并且还使用了'mapToScene(shape())'和'mapToScene(rect())'这些参数到'renderBackground'函数,但它有点关闭。今晚晚些时候我会更详细地研究你的代码。再次感谢。 – Justin

+0

好了,所以我仍然没有任何运气...当我这样做时,它似乎将背景从项目转换,因为'paint'函数使用项目坐标,当项目被拖动时不会改变。有没有办法在调用'renderBackground'函数后翻译画家对象? – Justin

+0

哦,是的,我看到了问题。上面的代码不处理该项目的位置。 (如果在将项目添加到场景之前调用'setPos()',您可能会遇到同样的问题。)我现在不在某个地方测试任何代码,但是如果您有Qt的源代码,检查'QGraphicsScene :: render()'方法。我敢打赌,他们暂时扭转了画家的转变,做了油漆,然后恢复了转变。对不起,我现在无法处理它。如果您仍然陷入困境,我会尽量在明天或周一发布解决方案! –