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. Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again

Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 4.4k Views 2 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.
  • P Offline
    P Offline
    Pippin
    wrote on last edited by
    #1

    Hello,

    here's a code sample:

    auto myQGraphicsScene = new QGraphicsScene();
    // ...
    auto myQWidget = new QWidget();
    // ...
    myQGraphicsScene->addWidget(myQWidget);
    // ...
    myQGraphicsScene->clear();
    // ...
    myQGraphicsScene->addWidget(myQWidget);
    

    I get a segmentation fault at the last line. What am I missing?

    Thanks in advance for your input!

    1 Reply Last reply
    0
    • kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #2

      Hi,
      The graphics scene takes ownership of the widget through the QGraphicsProxyWidget object returned by QGraphicsScene::addWidget. When you call QGraphicsScene::clear the scene deletes all items (including your widget), so myQWidget becomes a dangling pointer. After that you pass a pointer that references an invalid memory location to the QGraphicsScene::addWidget and ... voila! you get a segfault.

      Read and abide by the Qt Code of Conduct

      P 1 Reply Last reply
      2
      • kshegunovK kshegunov

        Hi,
        The graphics scene takes ownership of the widget through the QGraphicsProxyWidget object returned by QGraphicsScene::addWidget. When you call QGraphicsScene::clear the scene deletes all items (including your widget), so myQWidget becomes a dangling pointer. After that you pass a pointer that references an invalid memory location to the QGraphicsScene::addWidget and ... voila! you get a segfault.

        P Offline
        P Offline
        Pippin
        wrote on last edited by
        #3

        @kshegunov

        Thank you for the reply. To solve this tidily, could you please confirm that the following is efficient:

        For every QWidget added to the QGraphicsScene this way:

        1. Remove it from the QGraphicsScene thanks to QGraphicsScene::removeItem.
        2. delete its QGraphicsProxyWidget afterward.

        Is anything else required? Do I need to set the QWidget's parent to nullptr or anything else before adding it to the QGraphicsScene again?

        kshegunovK 1 Reply Last reply
        0
        • P Pippin

          @kshegunov

          Thank you for the reply. To solve this tidily, could you please confirm that the following is efficient:

          For every QWidget added to the QGraphicsScene this way:

          1. Remove it from the QGraphicsScene thanks to QGraphicsScene::removeItem.
          2. delete its QGraphicsProxyWidget afterward.

          Is anything else required? Do I need to set the QWidget's parent to nullptr or anything else before adding it to the QGraphicsScene again?

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

          Is anything else required?

          No, this should be just enough.

          Do I need to set the QWidget's parent to nullptr or anything else before adding it to the QGraphicsScene again?

          Nope, Qt should have done that for you when you removed the item from the scene.

          Read and abide by the Qt Code of Conduct

          P 1 Reply Last reply
          1
          • kshegunovK kshegunov

            @Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

            Is anything else required?

            No, this should be just enough.

            Do I need to set the QWidget's parent to nullptr or anything else before adding it to the QGraphicsScene again?

            Nope, Qt should have done that for you when you removed the item from the scene.

            P Offline
            P Offline
            Pippin
            wrote on last edited by Pippin
            #5

            @kshegunov said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

            Nope, Qt should have done that for you when you removed the item from the scene.

            Well technically I didn't remove the QWidget, but its QGraphicsProxyWidget. At this point, both QWidget's and QGraphicsProxyWidget's parent is nullptr then, correct?

            kshegunovK 1 Reply Last reply
            0
            • P Pippin

              @kshegunov said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

              Nope, Qt should have done that for you when you removed the item from the scene.

              Well technically I didn't remove the QWidget, but its QGraphicsProxyWidget. At this point, both QWidget's and QGraphicsProxyWidget's parent is nullptr then, correct?

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              @Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

              Well technically I didn't remove the QWidget, but its QGraphicsProxyWidget. At this point, both QWidget's and QGraphicsProxyWidget's parent is nullptr then, correct?

              I can't say for sure without actually testing it out, but you should get a QWidget that has a parent QGraphicsProxyWidget. Whereas the QGraphicsProxyWidget should have no parent.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • P Offline
                P Offline
                Pippin
                wrote on last edited by Pippin
                #7

                @kshegunov So this is the function I've been using:

                void freeWidget(QWidget* foo)
                {
                	const auto proxy = foo->graphicsProxyWidget();
                	myClass::myStaticQGraphicsScene->removeItem(proxy);
                	foo->setParent(nullptr);
                	delete proxy;
                }
                

                But even after that, when I add the QWidget again to myClass::myStaticQGraphicsScene, I get a segmentation fault. Sometimes the following message is printed shorty before:

                QGraphicsProxyWidget::setWidget: cannot embed widget 0x247f680; already embedded
                

                Any insight?

                1 Reply Last reply
                0
                • P Offline
                  P Offline
                  Pippin
                  wrote on last edited by Pippin
                  #8

                  I apologize but I'd like to bump this. Is there a way to set a Widget's QGraphicsProxyWidget to nullptr as well? Clearly what I'm doing isn't enough.

                  Solved: Indeed I had to set the Widget's QGraphicsProxyWidget to nullptr but the tricky part is, you can only do that from the QGraphicsProxyWidget, not from the QWidget. Here's the fixed freeWidget function:

                  void freeWidget(QWidget* foo)
                  {
                  	const auto proxy = foo->graphicsProxyWidget();
                  	myClass::myStaticQGraphicsScene->removeItem(proxy);
                  	proxy->setWidget(nullptr);
                  	foo->setParent(nullptr);
                  	delete proxy;
                  }
                  

                  Thanks again @kshegunov for your help yesterday.

                  (Edit: it seems that foo->setParent(nullptr); is useless.)

                  kshegunovK Q 2 Replies Last reply
                  0
                  • P Pippin

                    I apologize but I'd like to bump this. Is there a way to set a Widget's QGraphicsProxyWidget to nullptr as well? Clearly what I'm doing isn't enough.

                    Solved: Indeed I had to set the Widget's QGraphicsProxyWidget to nullptr but the tricky part is, you can only do that from the QGraphicsProxyWidget, not from the QWidget. Here's the fixed freeWidget function:

                    void freeWidget(QWidget* foo)
                    {
                    	const auto proxy = foo->graphicsProxyWidget();
                    	myClass::myStaticQGraphicsScene->removeItem(proxy);
                    	proxy->setWidget(nullptr);
                    	foo->setParent(nullptr);
                    	delete proxy;
                    }
                    

                    Thanks again @kshegunov for your help yesterday.

                    (Edit: it seems that foo->setParent(nullptr); is useless.)

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

                    Thanks for posting the solution.

                    @Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:

                    it seems that foo->setParent(nullptr); is useles

                    proxy->setWidget(nullptr);
                    

                    will set the widget's parent to null for you, yes.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0
                    • P Pippin

                      I apologize but I'd like to bump this. Is there a way to set a Widget's QGraphicsProxyWidget to nullptr as well? Clearly what I'm doing isn't enough.

                      Solved: Indeed I had to set the Widget's QGraphicsProxyWidget to nullptr but the tricky part is, you can only do that from the QGraphicsProxyWidget, not from the QWidget. Here's the fixed freeWidget function:

                      void freeWidget(QWidget* foo)
                      {
                      	const auto proxy = foo->graphicsProxyWidget();
                      	myClass::myStaticQGraphicsScene->removeItem(proxy);
                      	proxy->setWidget(nullptr);
                      	foo->setParent(nullptr);
                      	delete proxy;
                      }
                      

                      Thanks again @kshegunov for your help yesterday.

                      (Edit: it seems that foo->setParent(nullptr); is useless.)

                      Q Offline
                      Q Offline
                      QT_THE_GOD
                      wrote on last edited by
                      #10

                      @Pippin You are the best!!!! It's work!

                      1 Reply Last reply
                      0
                      • JoeCFDJ JoeCFD referenced this topic on
                      • SPlattenS SPlatten referenced this topic on

                      • Login

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