假設我們有2個qDeclarativeItem放在彼此的頂部。底部項目包含背景圖像(大部分時間保持不變)。頂部項目包含一些簡單的項目(直線,弧線......),可以使用鼠標直接編輯。qDeclarativeItem上的快速繪圖
問題: 當在頂層上繪畫時,buttom層也被完全重新繪製。考慮到我在那裏有一個大的圖像,重新繪製它非常緩慢。
作爲上述的一個例子,下面是一些代碼。
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QmlApplicationViewer viewer;
qmlRegisterType<BottomLayer>("Layer", 1, 0, "BottomLayer");
qmlRegisterType<UpperLayer>("Layer", 1, 0, "UpperLayer");
viewer.setMainQmlFile(QLatin1String("qml/main.qml"));
viewer.setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
viewer.showExpanded();
return app.exec();
}
背景層(繪製背景圖片):
BottomLayer::BottomLayer(QDeclarativeItem *parent) : QDeclarativeItem(parent)
{
setFlag(QGraphicsItem::ItemHasNoContents, false);
image.load("../img.png");
}
void BottomLayer::paint(QPainter* painter,const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->drawImage(QRectF(0, 0, 1920, 1080), image);
}
前景層(畫線):
UpperLayer::UpperLayer(QDeclarativeItem *parent) : QDeclarativeItem(parent)
{
setFlag(QGraphicsItem::ItemHasNoContents, false);
}
void UpperLayer::mousePosCanvasChanged(QPoint pos)
{
p2 = pos;
if(drawing)
update();
}
void UpperLayer::mouseDownCanvasChanged(QPoint pos)
{
p1 = pos;
drawing = true;
}
void UpperLayer::mouseUpCanvasChanged(QPoint pos)
{
drawing = false;
}
void UpperLayer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QPen pen(Qt::red, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
painter->drawLine(p1, p2);
}
QML代碼
Rectangle {
width: 1920
height: 1080
color: "transparent"
MouseArea {
anchors.fill: parent
onMousePositionChanged: upper_layer.mousePosCanvasChanged(Qt.point(mouseX,mouseY));
onPressed: upper_layer.mouseDownCanvasChanged(Qt.point(mouseX,mouseY))
onReleased: upper_layer.mouseUpCanvasChanged(Qt.point(mouseX,mouseY))
}
BottomLayer{
anchors.fill: parent
}
UpperLayer {
id: upper_layer
anchors.fill: parent
}
}
我是怎麼試試:
我試圖用viewer.setAttribute(Qt::WA_PaintOnScreen, true)
在屏幕上正確繪製所有東西,所以我可以避免緩衝開銷。這給了我想要的幀速率,但是一切都變成了閃爍。
我曾考慮過使用背景圖片作爲緩衝區,並對其進行繪畫。考慮到有時我必須自己清理(例如在屏幕上移動項目),這種方法變得過於複雜和不合理。
我試着用Graphics View Framework來做,所以我可以限制重繪區域到前景項目的剪輯矩形。然而,這不符合要求。如果f.ex.我有一條從左上角到右下角的線,clipRectangle覆蓋整個圖像(一切都很慢)。
我試着計算每個前景項目的clipRectangle並將它傳遞到update(QRect)
和update(QRegion)
。這給了我與GraphicsViewFramework相同的性能,但現在我可以將我的項目分成幾個矩形,分別重新繪製每個項目並獲得更小的重繪區域。如果我進一步採用這種方法,我可以逐個像素地更新每個項目,並且完全避免背景重繪。但是,我有一種感覺,我做錯了什麼。如果可以這樣做,Qt中沒有什麼能爲我做的一切嗎?
P.S.如果你有其他想法可以嘗試,我很樂意聽到(閱讀)它們。