2016-10-11 2 views
0

Disons que nous avons 2 qDeclarativeItem superposés. L'élément inférieur contient une image d'arrière-plan (la plupart du temps restant inchangée). L'élément supérieur contient un tas d'éléments simples (lignes, arcs ...) qui peuvent être édités directement à l'aide d'une souris.Dessiner rapidement sur un qDeclarativeItem

Problème: Lors de la peinture sur la couche supérieure, la couche de fond est entièrement repeinte. Considérant que j'ai une grande image là-bas, repeindre est très lent.

A titre d'exemple de ce qui précède, voici un certain code.

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(); 
} 

couche de fond (peinture l'image de fond):

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); 
} 

couche de premier plan (lignes de dessin):

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); 
} 

Code 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 
    } 
} 

Qu'est-ce que je cherche :

J'ai essayé de tout peindre directement sur l'écran avec viewer.setAttribute(Qt::WA_PaintOnScreen, true), donc je peux éviter de mettre en mémoire tampon. Cela me donne le taux de trame désiré, mais tout devient flickery. J'ai pensé à utiliser l'image d'arrière-plan comme tampon et à appliquer la peinture directement dessus. Considérant que parfois je dois nettoyer après moi-même (par exemple déplacer l'élément sur l'écran), cette approche devient trop complexe et injustifiée.

J'ai essayé de le faire avec Graphics View Framework, donc je peux limiter la zone de repeint au rectangle de clip de l'élément de premier plan. Cela ne fonctionne cependant pas comme souhaité. Si par exemple J'ai une ligne allant du coin supérieur gauche au coin inférieur droit, le clipRectangle couvre toute l'image (tout est de nouveau lent). J'ai essayé de calculer le clipRectangle pour chaque élément de premier plan et de le passer à update(QRect) et update(QRegion). Cela me donne la même performance que GraphicsViewFramework, mais, maintenant je peux diviser mes articles en plusieurs rectangles, repeindre chacun séparément et obtenir une zone de repeint encore plus petite. Si je vais plus loin avec cette approche, je peux mettre à jour chaque élément pixel par pixel et éviter de repeindre l'arrière-plan du tout. Cependant, j'ai le sentiment que je fais quelque chose de mal. S'il est possible de le faire de cette façon, n'y a-t-il pas quelque chose dans Qt qui puisse tout faire pour moi?

P.S. Si vous avez d'autres idées que je peux essayer, je suis intéressé à les entendre.

Répondre

0

Si l'image est inférieure à tous les articles et n'a pas besoin d'être déplacée, vous pouvez probablement utiliser QGraphicsView'::drawBackground()