Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsItem bad item drawing
Forum Updated to NodeBB v4.3 + New Features

QGraphicsItem bad item drawing

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 1.6k Views 1 Watching
  • 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.
  • L Offline
    L Offline
    Loc888
    wrote on last edited by
    #1

    I am trying to make a simple item, with some custom painting inside it, but unluckly as always, there are some problems... When i try to reimplement paint, it does work untill i move the item, then the old painting isn't removed, but it still appear on the screen, and this is only in the text area i added.

    img.png

    I tried to look it up, but nothing does fix it... If i try to take widget->update() then yes, it does work, but the performance is crap when i add let's say 1000 of items, the default QGraphicsRectItem works much faster, and i don't understand why that text is not removed.

    void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), rect().height()), "NONE");
        painter->drawRect(rect());
    }
    
    JonBJ Pl45m4P 2 Replies Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      Does your code meet the requirement in the first Note of the QGraphicsItem::paint() docs? Where does rect() come from? Does its value change independently?

      L 1 Reply Last reply
      0
      • L Loc888

        I am trying to make a simple item, with some custom painting inside it, but unluckly as always, there are some problems... When i try to reimplement paint, it does work untill i move the item, then the old painting isn't removed, but it still appear on the screen, and this is only in the text area i added.

        img.png

        I tried to look it up, but nothing does fix it... If i try to take widget->update() then yes, it does work, but the performance is crap when i add let's say 1000 of items, the default QGraphicsRectItem works much faster, and i don't understand why that text is not removed.

        void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
        {
            painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), rect().height()), "NONE");
            painter->drawRect(rect());
        }
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @Loc888 said in QGraphicsItem bad item drawing:

        rect().y() - 12

        rect.x/y() are the top-left coordinates of the rectangle (y() increases downwards). rect() (actually boundingRect() which I mention below) is the area being (re-)drawn; you are expected to draw within that rectangle. rect().y() - 12 draws outside the prescribed area. But Qt infrastructure does not know you have done that. I imagine you see that when you move the item downwards it leaves the top 12-odd pixels of the characters of NONE as they are, creating that "smear" pattern?

        @ChrisW67 drew you attention to https://doc.qt.io/qt-5/qgraphicsitem.html#paint:

        Make sure to constrain all painting inside the boundaries of boundingRect() to avoid rendering artifacts (as QGraphicsView does not clip the painter for you).

        You are indeed seeing such "artifacts" [sic.!!]

        You should draw within rect(). Try removing the - 12 --- does it work OK now?

        If you do need to draw the text above the rectangle, you need to override QRectF QGraphicsItem::boundingRect() const:

        This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be restricted to inside an item's bounding rect. QGraphicsView uses this to determine whether the item requires redrawing.
        Reimplement this function to let QGraphicsView determine what parts of the widget, if any, need to be redrawn.

        You need to expanding the bounding rectangle to encompass all areas you draw into.

        L 1 Reply Last reply
        1
        • L Loc888

          I am trying to make a simple item, with some custom painting inside it, but unluckly as always, there are some problems... When i try to reimplement paint, it does work untill i move the item, then the old painting isn't removed, but it still appear on the screen, and this is only in the text area i added.

          img.png

          I tried to look it up, but nothing does fix it... If i try to take widget->update() then yes, it does work, but the performance is crap when i add let's say 1000 of items, the default QGraphicsRectItem works much faster, and i don't understand why that text is not removed.

          void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
          {
              painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), rect().height()), "NONE");
              painter->drawRect(rect());
          }
          
          Pl45m4P Offline
          Pl45m4P Offline
          Pl45m4
          wrote on last edited by Pl45m4
          #4

          @Loc888

          As @JonB explained in detail, if your "text" (or any other part of your item), is outside the item's boundingRect, even when it's just one pixel, it behaves like a brush. So you "paint" with a "None"-shaped (literally) brush on your canvas / background... And it is permanent until this area gets updated again, for example when you move the item's boundingRect over that area.
          That's why you only see it, when you drag your item downwards. Because when you drag upwards, the item's boundingRect follows after your "None"-text and clears that area again.

          So make sure the text is inside the boundingRect of your item or create an extra Textitem and attach it to your rect_item.


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          0
          • C ChrisW67

            Does your code meet the requirement in the first Note of the QGraphicsItem::paint() docs? Where does rect() come from? Does its value change independently?

            L Offline
            L Offline
            Loc888
            wrote on last edited by
            #5

            @ChrisW67 The rect comes from the rect item it self, i didn't read the documentation, since the code was so simplistic, that i didn't find the need to be honest, but i look up similar problems and the solutions for them didn't fix my problem.

            1 Reply Last reply
            0
            • JonBJ JonB

              @Loc888 said in QGraphicsItem bad item drawing:

              rect().y() - 12

              rect.x/y() are the top-left coordinates of the rectangle (y() increases downwards). rect() (actually boundingRect() which I mention below) is the area being (re-)drawn; you are expected to draw within that rectangle. rect().y() - 12 draws outside the prescribed area. But Qt infrastructure does not know you have done that. I imagine you see that when you move the item downwards it leaves the top 12-odd pixels of the characters of NONE as they are, creating that "smear" pattern?

              @ChrisW67 drew you attention to https://doc.qt.io/qt-5/qgraphicsitem.html#paint:

              Make sure to constrain all painting inside the boundaries of boundingRect() to avoid rendering artifacts (as QGraphicsView does not clip the painter for you).

              You are indeed seeing such "artifacts" [sic.!!]

              You should draw within rect(). Try removing the - 12 --- does it work OK now?

              If you do need to draw the text above the rectangle, you need to override QRectF QGraphicsItem::boundingRect() const:

              This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be restricted to inside an item's bounding rect. QGraphicsView uses this to determine whether the item requires redrawing.
              Reimplement this function to let QGraphicsView determine what parts of the widget, if any, need to be redrawn.

              You need to expanding the bounding rectangle to encompass all areas you draw into.

              L Offline
              L Offline
              Loc888
              wrote on last edited by
              #6

              @JonB

              QRectF Rectangle_Item::boundingRect() const
              {
              return QRect(rect().x(), rect().y(), rect().width()+15, rect().height()+15);
              }

              At the begining i did -12 in boundingRect but on the x side by mistake..... Then i concluded that the problem must be too small rect, so i increased the size of it as in the code above, but i forgot to correct the y position, the problem is fixed if i add this:

              QRectF Rectangle_Item::boundingRect() const
              {
              return QRect(rect().x(), rect().y() - 13, rect().width()+13, rect().height()+13);
              }

              Nevermind, that's how you endup when you code late morning when you suppose to be sleeping for like few hours.

              JonBJ 1 Reply Last reply
              0
              • L Loc888

                @JonB

                QRectF Rectangle_Item::boundingRect() const
                {
                return QRect(rect().x(), rect().y(), rect().width()+15, rect().height()+15);
                }

                At the begining i did -12 in boundingRect but on the x side by mistake..... Then i concluded that the problem must be too small rect, so i increased the size of it as in the code above, but i forgot to correct the y position, the problem is fixed if i add this:

                QRectF Rectangle_Item::boundingRect() const
                {
                return QRect(rect().x(), rect().y() - 13, rect().width()+13, rect().height()+13);
                }

                Nevermind, that's how you endup when you code late morning when you suppose to be sleeping for like few hours.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                @Loc888
                Correct principle. There is no reason for rect().width()+13. Unless you have altered anything I think you should have:

                void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
                {
                    painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), 12 /* altered*/), "NONE");
                    painter->drawRect(rect());
                }
                

                and

                QRectF Rectangle_Item::boundingRect() const
                {
                    return QRect(rect().x(), rect().y() - 13, rect().width() /* altered*/, rect().height()+13);
                }
                
                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