2016-10-11 46 views
0

假设我们有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.如果你有其他想法可以尝试,我很乐意听到(阅读)它们。

回答

0

如果图像低于所有项目并且不需要移动,则可以将其绘制在QGraphicsView'::drawBackground()