Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. How to redraw a custom QQuickItem
QtWS25 Last Chance

How to redraw a custom QQuickItem

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
qt quickqsggeometry
4 Posts 2 Posters 7.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • chaithubkC Offline
    chaithubkC Offline
    chaithubk
    wrote on last edited by
    #1

    I have created a custom QML Element by extending QQuickItem and overriding the updatePaintNode() function. I am drawing two lines on my application which will expand or shrink in size based on the block size that gets added on the left side of the application. This block can be added in small and big modes and can be removed by selecting the buttons on the top bar.

    This is my code:

    line.cpp

    #include <QSGGeometry>
    #include <QSGGeometryNode>
    #include <qsgnode.h>
    #include <qsgflatcolormaterial.h>
    #include "line.h"
    
    Lines::Lines(QQuickItem *parent) : QQuickItem(parent) {
        setFlag(QQuickItem::ItemHasContents, true);
    }
    
    Lines::~Lines() {}
    
    QSGNode *Lines::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) {
        QSGGeometryNode *node = NULL;
        QSGGeometry *geometry = NULL;
        QSGGeometry::Point2D *vertices;
        QSGFlatColorMaterial *material;
        int points = 0;
        int lineHeight = 0;
        int ys = 0;
        int xs;
        int xe;
    
        points = width();
    
        if (!oldNode)
        {
            node = new QSGGeometryNode;
            geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), points);
            geometry->setLineWidth(1);
            geometry->setDrawingMode(GL_LINES);
            node->setGeometry(geometry);
            node->setFlag(QSGNode::OwnsGeometry);
            material = new QSGFlatColorMaterial;
            material->setColor("white");
            node->setMaterial(material);
            node->setFlag(QSGNode::OwnsMaterial);
        }
        else
        {
            node = static_cast<QSGGeometryNode *>(oldNode);
            geometry = node->geometry();
            geometry->allocate(points);
        }
    
        vertices = geometry->vertexDataAsPoint2D();
        lineHeight = (height() / 4);
    
        xs = 0;
        xe = width() - xs;
    
        for(int i = 0; i < 2; i++)
        {
            ys = ( i * lineHeight);
            vertices[(2*i)].set(xs, ys);
            vertices[(2*i)+1].set(xs + xe, ys);
        }
    
        node->markDirty(QSGNode::DirtyForceUpdate);
        return node;
    }
    

    line.h

    #include <QQuickItem>
    class Lines : public QQuickItem
    {
        Q_OBJECT
    public:
        Lines(QQuickItem *parent = 0);
        ~Lines();
    
        QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
    };
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include "line.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        qmlRegisterType<Lines>("lines", 1, 0, "Lines");
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.0
    import lines 1.0
    
    Window {
        id: canvas
    
        height: 500
        width: 500
        color: "black"
        visible: true
    
        Rectangle {
            id: topBar
    
            height: 40
            Row {
                spacing: 10
                Button {
                    text: "Small"
                    onClicked: {
                        rect.visible = true
                        rect.width = 50
                    }
                }
                Button {
                    text: "Big"
                    onClicked: {
                        rect.visible = true
                        rect.width = 100
                    }
                }
                Button {
                    text: "None"
                    onClicked: {
                        rect.visible = false
                        rect.width = 0
                    }
                }
            }
        }
    
        Rectangle {
            id: rect
    
            anchors {
                left: parent.left
                top: topBar.bottom
                bottom: parent.bottom
            }
    
            color: "grey"
            visible: false
        }
    
        Rectangle {
            id: rect2
    
            anchors {
                left: rect.right
                right: parent.right
                top: topBar.bottom
                bottom: parent.bottom
            }
    
            color: "black"
    
            Lines {
                id: lines
    
                x: 0
                y: 100
    
                width: parent.width
                height: 225
            }
        }
    }
    

    I am seeing that when I select the left Grey block (using the buttons) the Lines were not redrawn properly and I see some glitches. The attached picture below shows my output with glitches.

    0_1499167266627_fS7Lo.png

    I have tried calling node->markDirty(QSGNode::DirtyForceUpdate) but it is of no use.

    How can I fix this issue. Please help. Thanks in advance.

    raven-worxR 1 Reply Last reply
    0
    • chaithubkC chaithubk

      I have created a custom QML Element by extending QQuickItem and overriding the updatePaintNode() function. I am drawing two lines on my application which will expand or shrink in size based on the block size that gets added on the left side of the application. This block can be added in small and big modes and can be removed by selecting the buttons on the top bar.

      This is my code:

      line.cpp

      #include <QSGGeometry>
      #include <QSGGeometryNode>
      #include <qsgnode.h>
      #include <qsgflatcolormaterial.h>
      #include "line.h"
      
      Lines::Lines(QQuickItem *parent) : QQuickItem(parent) {
          setFlag(QQuickItem::ItemHasContents, true);
      }
      
      Lines::~Lines() {}
      
      QSGNode *Lines::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) {
          QSGGeometryNode *node = NULL;
          QSGGeometry *geometry = NULL;
          QSGGeometry::Point2D *vertices;
          QSGFlatColorMaterial *material;
          int points = 0;
          int lineHeight = 0;
          int ys = 0;
          int xs;
          int xe;
      
          points = width();
      
          if (!oldNode)
          {
              node = new QSGGeometryNode;
              geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), points);
              geometry->setLineWidth(1);
              geometry->setDrawingMode(GL_LINES);
              node->setGeometry(geometry);
              node->setFlag(QSGNode::OwnsGeometry);
              material = new QSGFlatColorMaterial;
              material->setColor("white");
              node->setMaterial(material);
              node->setFlag(QSGNode::OwnsMaterial);
          }
          else
          {
              node = static_cast<QSGGeometryNode *>(oldNode);
              geometry = node->geometry();
              geometry->allocate(points);
          }
      
          vertices = geometry->vertexDataAsPoint2D();
          lineHeight = (height() / 4);
      
          xs = 0;
          xe = width() - xs;
      
          for(int i = 0; i < 2; i++)
          {
              ys = ( i * lineHeight);
              vertices[(2*i)].set(xs, ys);
              vertices[(2*i)+1].set(xs + xe, ys);
          }
      
          node->markDirty(QSGNode::DirtyForceUpdate);
          return node;
      }
      

      line.h

      #include <QQuickItem>
      class Lines : public QQuickItem
      {
          Q_OBJECT
      public:
          Lines(QQuickItem *parent = 0);
          ~Lines();
      
          QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
      };
      

      main.cpp

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include "line.h"
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
          qmlRegisterType<Lines>("lines", 1, 0, "Lines");
      
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      
          return app.exec();
      }
      

      main.qml

      import QtQuick 2.4
      import QtQuick.Window 2.2
      import QtQuick.Controls 1.0
      import lines 1.0
      
      Window {
          id: canvas
      
          height: 500
          width: 500
          color: "black"
          visible: true
      
          Rectangle {
              id: topBar
      
              height: 40
              Row {
                  spacing: 10
                  Button {
                      text: "Small"
                      onClicked: {
                          rect.visible = true
                          rect.width = 50
                      }
                  }
                  Button {
                      text: "Big"
                      onClicked: {
                          rect.visible = true
                          rect.width = 100
                      }
                  }
                  Button {
                      text: "None"
                      onClicked: {
                          rect.visible = false
                          rect.width = 0
                      }
                  }
              }
          }
      
          Rectangle {
              id: rect
      
              anchors {
                  left: parent.left
                  top: topBar.bottom
                  bottom: parent.bottom
              }
      
              color: "grey"
              visible: false
          }
      
          Rectangle {
              id: rect2
      
              anchors {
                  left: rect.right
                  right: parent.right
                  top: topBar.bottom
                  bottom: parent.bottom
              }
      
              color: "black"
      
              Lines {
                  id: lines
      
                  x: 0
                  y: 100
      
                  width: parent.width
                  height: 225
              }
          }
      }
      

      I am seeing that when I select the left Grey block (using the buttons) the Lines were not redrawn properly and I see some glitches. The attached picture below shows my output with glitches.

      0_1499167266627_fS7Lo.png

      I have tried calling node->markDirty(QSGNode::DirtyForceUpdate) but it is of no use.

      How can I fix this issue. Please help. Thanks in advance.

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @chaithubk
      simply call update() like you would do for a QWidget

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      chaithubkC 1 Reply Last reply
      0
      • raven-worxR raven-worx

        @chaithubk
        simply call update() like you would do for a QWidget

        chaithubkC Offline
        chaithubkC Offline
        chaithubk
        wrote on last edited by chaithubk
        #3

        @raven-worx You mean like I need to call Lines::update() in the updatePaintNode() function ? I have not worked on Qt Widgets. So am little confused with your solution.

        raven-worxR 1 Reply Last reply
        0
        • chaithubkC chaithubk

          @raven-worx You mean like I need to call Lines::update() in the updatePaintNode() function ? I have not worked on Qt Widgets. So am little confused with your solution.

          raven-worxR Offline
          raven-worxR Offline
          raven-worx
          Moderators
          wrote on last edited by
          #4

          @chaithubk
          whenever data relevant for drawing has changed call update() on the QQuickItem and a call to updatePaintNode() (-> painting) is scheduled.
          Like in is mentioned in the link to the docs i've posted.

          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
          If you have a question please use the forum so others can benefit from the solution in the future

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved