2012-06-15 53 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()'方法。我敢打賭,他們暫時扭轉了畫家的轉變,做了油漆,然後恢復了轉變。對不起,我現在無法處理它。如果您仍然陷入困境,我會盡量在明天或週一發佈解決方案! –