假设我们有2个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。如果您有其他一些我可以尝试的想法,我很想听(读)它们。
答案 0 :(得分:0)
如果图片位于所有项目下方且无需移动,则可以在QGraphicsView'::drawBackground()