項目是基於Qt的圖形視圖框架編寫的,現有個需求是要在圖形中加入自定義的背景圖片。心想不就是個背景圖片嗎?只要重寫drawBackground函數我想怎麼畫就怎麼畫啊。於是立馬從QGraphicsScene類中派生了一個CScene類,並重寫了虛函數drawBackground。在該函數中繪製了一張圖片。
void CScene::drawBackground(QPainter *painter, const QRectF &rect){QPixmap pixmap("F:/05_test/back.jpg"); painter->drawPixmap(rect,pixmap,QRect()); //在rect範圍內繪製圖片}
看看這效果,so easy啊。但是如果故事到這裡就結束的話那就沒意思了。 接下來我在場景中添加了兩個矩形圖元並拖動一個矩形。於是出現了詭異的一幕。
//創建並添加兩個矩形圖元到場景中
QGraphicsRectItem* rectItem1 = new QGraphicsRectItem(-20,-20,40,40);
rectItem1->setFlag(QGraphicsItem::ItemIsMovable);
QGraphicsRectItem* rectItem2 = new QGraphicsRectItem(-30,-30,60,60);
rectItem2->setFlag(QGraphicsItem::ItemIsMovable);
rectItem2->setPos(100,100);
m_pScene->addItem(rectItem1);
m_pScene->addItem(rectItem2);
戒指不見了!戒指跑哪裡去了?
扯遠了,其實是圖形中出現了殘影現象,那麼為什麼會有殘影呢?難道是圖元的刷新範圍不正確嗎?於是設置視圖的更新模式試試。
m_pView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
設置為FullViewportUpdate後重啟程序再拖動圖元發現殘影不見了。
然而事情到這一步還是沒有結束,接下來我又在視圖上加了個QLabel,並且嘗試移動它。
label = new QLabel(m_pView); label->setStyleSheet("background:red;"); label->setFixedSize(100,100); label->move(100,50);
戒指又不見了!(殘影又出現了)。看來設置視圖的更新模式只能對圖元起作用啊。
那怎麼辦呢?仔細觀察第一次出現的殘影,會發現矩形圖元裡居然也有背景圖片。我們並沒有給圖元設置背景圖片啊,這就更詭異了。
其實矩形圖元裡的背景圖片並不屬於矩形圖元,之前出現的殘影也不是更新圖元或QLabel產生的。一切都是drawBackground的第二個參數在搞鬼。Qt幫助文檔告訴我們rect是指暴露的矩形,我還以為是視圖當前可視的矩形區域。然而事實卻不是這樣。列印出rect的值:
rect: QRectF(-133,-83 376x276)
rect: QRectF(67,66 66x67)
rect: QRectF(67,65 66x67)
程序剛啟動時rect的大小是視圖的窗口大小,拖動圖元時函數給我們的rect只是比圖元大一點,很顯然不能滿足我們的需求,至於為什麼是這樣也不知道。所以我們需要繪製的圖片始終和視圖一樣大需要自己計算,可以這麼寫。
if(views().count() == 0) return; QGraphicsView* pView = views().first(); QRect contentRect = pView->viewport()->contentsRect(); QRectF sceneRect = pView->mapToScene(contentRect).boundingRect(); QPixmap pixmap("F:/05_test/back.jpg"); painter->drawPixmap(sceneRect,pixmap,QRect()); //在rect範圍內繪製圖片
測試環境:Qt5.9.4