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. QGraphicsScene and event handling
Forum Update on Monday, May 27th 2025

QGraphicsScene and event handling

Scheduled Pinned Locked Moved Solved General and Desktop
qgraphicssceneeventsremoveitem
5 Posts 3 Posters 706 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.
  • Q Offline
    Q Offline
    QtUser467
    wrote on last edited by
    #1

    I have an application with a QGraphicsScene.

    In the event handler of the scene, I process mouse (and tablet) events. For example, I determine whether the pointer is on particular items and select or move them, or create new items that are added to the scene. I do not use the built-in functions like drag Events.

    This kind of works, but I ran into a range of problems:

    The first is that I noticed artifacts when quickly moving the mouse around (e.g. moving the end point of a line) Despite correct bounding boxes and calls to prepareGeometryChange(), sometimes artifacts remained at the periphery of the bounding box. The same applied when showing or hiding entire items.
    This problem disappeared when I set setCacheMode(QGraphicsView::CacheBackground); and setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); for the view.

    The next problem was that when I called removeItem(item) to remove items from the scene, sometimes the items remained visible, although they were no longer "there" (not in items(). And when I deleted the items, the applications sometimes segfaulted when painting the scene because it tried to re-draw the item that were removed. Apparently, the removed items were still in the BSPTree the scene maintains to find items in
    given screen areas. This problem disappeared when I set setItemIndexMethod(QGraphicsScene::ItemIndexMethod::NoIndex); in the scene.

    Overall, this accumulation of problems seem to indicate that I do not use the QGraphicsScene as intended by its designers.

    I found several similar reports, and the way I understand them is that modifications to the scene should not be done in its event handler, but in the main GUI thread.

    If this is true, then the problem emerges how to determine, in the event handler, whether an event should be accepted or passed on to the parent item's method.
    For example, it seems possible that an item is scheduled to be removed, but that the removal has not yet taken place because the main Gui thread has not yet called the corresponding code. In this case, the event handler code would still "see" the item.

    So overall my questions are:

    • Is it true that scene modifications should not take place in the event handler?

    • How are what the event handler and the main GUI thread "see" of the scene kept synchronized?

    A 1 Reply Last reply
    0
    • A Asperamanca

      @QtUser467 The event handler runs in the main thread. So there is no special need to keep them synchronized.
      However, deleting items inside an event handler is...tricky. Consider:

      CMyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
      {
        // some condition
        {
          delete this;
          return;
        }
      }
      

      Safe? I think not. This would be inside the item's event handler, but I see deleting an item inside the QGraphicsScene's event handler similar: The item's pointer might still exist in a list of items to deliver the event to. GraphicsView cannot check and filter those lists after every call to a customized event handler function. Therefore, I would recommend only deleting items between events. Hide them and put them into a "delete list" (or use deleteLater() if they are QObjects anyway).

      Regarding drawing artifacts: Are you sure your boundingRect() still returns the previous value at the time where you call prepareGeometryChange? That's important: You need to call it before changing any values that will affect output of boundingRect()

      Q Offline
      Q Offline
      QtUser467
      wrote on last edited by
      #3

      I have now moved all event handling out of the event handler, with a Qt::QueuedConnection. I also found a case where prepareGeometryChange() was not called before a change in boundingRect. This has solved the issue.

      Pl45m4P 1 Reply Last reply
      0
      • Q QtUser467

        I have an application with a QGraphicsScene.

        In the event handler of the scene, I process mouse (and tablet) events. For example, I determine whether the pointer is on particular items and select or move them, or create new items that are added to the scene. I do not use the built-in functions like drag Events.

        This kind of works, but I ran into a range of problems:

        The first is that I noticed artifacts when quickly moving the mouse around (e.g. moving the end point of a line) Despite correct bounding boxes and calls to prepareGeometryChange(), sometimes artifacts remained at the periphery of the bounding box. The same applied when showing or hiding entire items.
        This problem disappeared when I set setCacheMode(QGraphicsView::CacheBackground); and setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); for the view.

        The next problem was that when I called removeItem(item) to remove items from the scene, sometimes the items remained visible, although they were no longer "there" (not in items(). And when I deleted the items, the applications sometimes segfaulted when painting the scene because it tried to re-draw the item that were removed. Apparently, the removed items were still in the BSPTree the scene maintains to find items in
        given screen areas. This problem disappeared when I set setItemIndexMethod(QGraphicsScene::ItemIndexMethod::NoIndex); in the scene.

        Overall, this accumulation of problems seem to indicate that I do not use the QGraphicsScene as intended by its designers.

        I found several similar reports, and the way I understand them is that modifications to the scene should not be done in its event handler, but in the main GUI thread.

        If this is true, then the problem emerges how to determine, in the event handler, whether an event should be accepted or passed on to the parent item's method.
        For example, it seems possible that an item is scheduled to be removed, but that the removal has not yet taken place because the main Gui thread has not yet called the corresponding code. In this case, the event handler code would still "see" the item.

        So overall my questions are:

        • Is it true that scene modifications should not take place in the event handler?

        • How are what the event handler and the main GUI thread "see" of the scene kept synchronized?

        A Offline
        A Offline
        Asperamanca
        wrote on last edited by
        #2

        @QtUser467 The event handler runs in the main thread. So there is no special need to keep them synchronized.
        However, deleting items inside an event handler is...tricky. Consider:

        CMyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
        {
          // some condition
          {
            delete this;
            return;
          }
        }
        

        Safe? I think not. This would be inside the item's event handler, but I see deleting an item inside the QGraphicsScene's event handler similar: The item's pointer might still exist in a list of items to deliver the event to. GraphicsView cannot check and filter those lists after every call to a customized event handler function. Therefore, I would recommend only deleting items between events. Hide them and put them into a "delete list" (or use deleteLater() if they are QObjects anyway).

        Regarding drawing artifacts: Are you sure your boundingRect() still returns the previous value at the time where you call prepareGeometryChange? That's important: You need to call it before changing any values that will affect output of boundingRect()

        Q 1 Reply Last reply
        2
        • A Asperamanca

          @QtUser467 The event handler runs in the main thread. So there is no special need to keep them synchronized.
          However, deleting items inside an event handler is...tricky. Consider:

          CMyGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
          {
            // some condition
            {
              delete this;
              return;
            }
          }
          

          Safe? I think not. This would be inside the item's event handler, but I see deleting an item inside the QGraphicsScene's event handler similar: The item's pointer might still exist in a list of items to deliver the event to. GraphicsView cannot check and filter those lists after every call to a customized event handler function. Therefore, I would recommend only deleting items between events. Hide them and put them into a "delete list" (or use deleteLater() if they are QObjects anyway).

          Regarding drawing artifacts: Are you sure your boundingRect() still returns the previous value at the time where you call prepareGeometryChange? That's important: You need to call it before changing any values that will affect output of boundingRect()

          Q Offline
          Q Offline
          QtUser467
          wrote on last edited by
          #3

          I have now moved all event handling out of the event handler, with a Qt::QueuedConnection. I also found a case where prepareGeometryChange() was not called before a change in boundingRect. This has solved the issue.

          Pl45m4P 1 Reply Last reply
          0
          • Q QtUser467

            I have now moved all event handling out of the event handler, with a Qt::QueuedConnection. I also found a case where prepareGeometryChange() was not called before a change in boundingRect. This has solved the issue.

            Pl45m4P Offline
            Pl45m4P Offline
            Pl45m4
            wrote on last edited by Pl45m4
            #4

            @QtUser467 said in QGraphicsScene and event handling:

            I have now moved all event handling out of the event handler, with a Qt::QueuedConnection

            Usually there's no need to specify this option yourself. Let the connect "decide".
            You must use Qt::QueuedConnection when sending signals across different threads, but even then Qt will notice that sender and receiver don't live in the same thread.

            Regarding your artifacts:
            Due to optimization, not the whole scene is redrawn after operation, so if somehow some painted path/region of a (re-)moved or resized item exceeds the boundingRect, this area might not get updated. Therefore remains might stay visible.


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

            ~E. W. Dijkstra

            Q 1 Reply Last reply
            0
            • Pl45m4P Pl45m4

              @QtUser467 said in QGraphicsScene and event handling:

              I have now moved all event handling out of the event handler, with a Qt::QueuedConnection

              Usually there's no need to specify this option yourself. Let the connect "decide".
              You must use Qt::QueuedConnection when sending signals across different threads, but even then Qt will notice that sender and receiver don't live in the same thread.

              Regarding your artifacts:
              Due to optimization, not the whole scene is redrawn after operation, so if somehow some painted path/region of a (re-)moved or resized item exceeds the boundingRect, this area might not get updated. Therefore remains might stay visible.

              Q Offline
              Q Offline
              QtUser467
              wrote on last edited by QtUser467
              #5

              @Pl45m4 said in QGraphicsScene and event handling:

              Due to optimization, not the whole scene is redrawn after operation, so if somehow some painted path/region of a (re-)moved or resized item exceeds the boundingRect, this area might not get updated. Therefore remains might stay visible.

              This indeed was one problem. The other one was that despite the call to removeItem(), the item stayed in the BSPTree, because the boundingRect changed without a previous call to prepareGeometryChange() (which I had everywhere except in this hidden case). Clearly my fault! Overall, this is not very fault tolerant and also not easy to debug! In a way, it would be nice to have a function that could be called (during debugging) to do some consistency checking, rather than only finding out much later during a paint event.

              1 Reply Last reply
              0
              • Q QtUser467 has marked this topic as solved on

              • Login

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