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. Clearing Out a Layout
QtWS25 Last Chance

Clearing Out a Layout

Scheduled Pinned Locked Moved General and Desktop
21 Posts 3 Posters 22.4k 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.
  • A Offline
    A Offline
    Arukas
    wrote on 19 Jan 2012, 06:04 last edited by
    #10

    I didn't try your code out, but I did what you did, or at least I think you did. You created a QWidget,m_layout2Hodler, and added the desired layout to it and its the m_layout2Hodler you added not the actual layout. Then when you want the layout gone you delete the QWidget.

    I implemented that in my code, and I couldn't get it to work. Still the exact same problem.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Arukas
      wrote on 19 Jan 2012, 06:08 last edited by
      #11

      Here's some of my code I'm using, if that helps.

      @MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
      {
      ui->setupUi(this);
      connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(addComboLine()));
      connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(removeAll()));

      }

      MainWindow::~MainWindow()
      {
      delete ui;
      }

      void MainWindow::addComboLine()
      {
      QLabel *label = new QLabel;
      QLineEdit *lineEdit = new QLineEdit;
      QHBoxLayout hLayout = new QHBoxLayout;
      QWidget
      stupidKid = new QWidget;

      label->setText("Hello!");
      hLayout->addWidget(label);
      hLayout->addWidget(lineEdit);
      stupidKid->setLayout(hLayout);
      ui->verticalLayout->addWidget(stupidKid);
      

      }

      void MainWindow::removeAll()
      {
      QLayoutItem* child;
      child=ui->verticalLayout->takeAt(0);
      while(child != 0)
      {
      ui->verticalLayout->removeWidget(child->widget());
      delete child;
      child=ui->verticalLayout->takeAt(0);
      }

      }@

      1 Reply Last reply
      0
      • A Offline
        A Offline
        Arukas
        wrote on 19 Jan 2012, 06:19 last edited by
        #12

        I did some playing around and I just hide the widget first. If I don't hide the widget first, it totally destroys my GUI. Or should I use a @delete child->widget();@

        Here's my Code:
        @void MainWindow::addComboLine()
        {
        QWidget* stupidKid = new QWidget;
        QLabel *label = new QLabel;
        QLineEdit *lineEdit = new QLineEdit;
        QHBoxLayout *hLayout = new QHBoxLayout;

        label->setText("Hello!");
        hLayout->addWidget(label);
        hLayout->addWidget(lineEdit);
        stupidKid->setLayout(hLayout);
        ui->verticalLayout->addWidget(stupidKid);
        

        }

        void MainWindow::removeAll()
        {
        QLayoutItem* child;
        child=ui->verticalLayout->takeAt(0);
        while(child != 0)
        {
        if(child->widget()!=0)
        child->widget()->hide();
        ui->verticalLayout->removeWidget(child->widget());
        delete child;
        child=ui->verticalLayout->takeAt(0);
        //ui->verticalLayout->update();
        }
        }
        @

        1 Reply Last reply
        0
        • L Offline
          L Offline
          lgeyer
          wrote on 19 Jan 2012, 06:44 last edited by
          #13

          The first code snippet is fine, works as expected and should be used to clear layouts.

          The problem is the second snippet. You call <code>show()</code> on a widget that is embedded within an layout, which means it is shown as a top-level window as soon as it is removed from the layout. This is not how layouts are meant to be used.

          A layout takes several child widgets and is then set on a widget using QWidget::setLayout(), which is then shown.
          @
          QVBoxLayout* layout = new QVBoxLayout;
          layout->addWidget(new QLabel("Label 1"));
          layout->addWidget(new QLabel("Label 2"));

          QWidget* widget = new QWidget;
          widget->setLayout(layout);
          widget->show();
          @
          In your case it is most probably <code>show()</code> or <code>this->show()</code>, not <code>Something->show()</code>.

          Be aware that QLayoutItem::widget() might not neccessarily return a valid widget. So your third snippet doesn't break immediately for the simple fact that <code>delete 0</code> is allowed in C++. [quote]
          If this item is a QWidget, it is returned as a QWidget; otherwise 0 is returned. This function provides type-safe casting.[/quote]
          In addition, this snippet leaks memory, because you just delete the widget the QLayoutItem* <code>child</code> points to and not the QLayoutItem itself, which is dangling from now on because it has been taken out of the layouts child collection.

          EDIT As this discussion has been merged this post relates to post #1 and #2 (which was the actual discussion).

          1 Reply Last reply
          0
          • J Offline
            J Offline
            joonhwan
            wrote on 19 Jan 2012, 08:01 last edited by
            #14

            Then.. What I meant was....

            @
            MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
            {
            ui->setupUi(this);

            // assume put all your ui inside a plain vanilla QWidget as a
            // simple placeholder for childrend widgets
            //
            // for example, in QtDesginer,
            // 1) you cut all your widgets
            // 2) add a plain vanilla QWidget (named 'placeHolder' whatever)
            // 3) click horizontally layout to make this new widget cover whole client area
            // 4) paste the cut'd widgets inside of this new widget
            // 5) now, the old 'verticalLayout' is the layout of 'placeHolder' widget
            // (was layout of MainWindow I think, though I cannot check your ui file)

            connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(addComboLine()));
            connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(removeAll()));

            }

            MainWindow::~MainWindow()
            {
            delete ui;
            }

            void MainWindow::addComboLine()
            {
            QLabel *label = new QLabel;
            QLineEdit *lineEdit = new QLineEdit;
            QHBoxLayout hLayout = new QHBoxLayout;
            QWidget
            stupidKid = new QWidget;

            label->setText("Hello!");
            hLayout->addWidget(label);
            hLayout->addWidget(lineEdit);
            stupidKid->setLayout(hLayout);

            ui->verticalLayout->addWidget(stupidKid);
            }

            void MainWindow::removeAll()
            {
            // QLayoutItem* child;
            // child=ui->verticalLayout->takeAt(0);
            // while(child != 0)
            // {
            // ui->verticalLayout->removeWidget(child->widget());
            // delete child;
            // child=ui->verticalLayout->takeAt(0);
            // }
            delete ui->placeHolder;
            ui->placeHolder = 0;
            }
            @

            though I have to say i've not tested above code yet.

            joonhwan at gmail dot com

            1 Reply Last reply
            0
            • L Offline
              L Offline
              lgeyer
              wrote on 19 Jan 2012, 09:34 last edited by
              #15

              There is no need for a placeholder widget just to add a layout to another layout. All layouts have in addition to addWidget() an addLayout() method which allows for directly adding a layout.

              An exception to this rule is QStackedLayout and QFormLayout, but it doesn't make sense adding layouts instead of widgets to them anyways. However, those layouts can be of course added freely to any other layout.

              @
              void MainWindow::addComboLine()
              {
              QHBoxLayout* layout = new QHBoxLayout;

              layout->addWidget(new QLabel("Hello!"));
              layout->addWidget(new QLineEdit);
              
              ui->verticalLayout->addLayout(layout);
              

              }

              void MainWindow::remove(QLayout* layout)
              {
              QLayoutItem* child;
              while((child = layout->takeAt(0)) != 0)
              {
              if(child->layout() != 0)
              {
              remove(child->layout());
              }
              else if(child->widget() != 0)
              {
              delete child->widget();
              }

                  delete child;
              }
              

              }

              void MainWindow::removeAll()
              {
              remove(ui->verticalLayout);
              }
              @
              Brain to terminal. Not tested. Exemplary.

              EDIT If you add layouts instead of widgets to a layout, it's children are of course layouts too. So the code needed a bit recursivity to work properly. It indeed removes the items from the layout without recursion, but as widgets placed in layouts have the layouts parent widget as parent (and not the layout itself) the widgets are not deleted along with the layout.

              1 Reply Last reply
              0
              • J Offline
                J Offline
                joonhwan
                wrote on 19 Jan 2012, 10:46 last edited by
                #16

                Yes you're right, maybe no need to use a place holder widget. But I thought
                @
                delete placeHolder;
                @

                is much simpler, clearer and readable than followings, IMHO

                @
                QLayoutItem* child;
                while ((child = ui->verticalLayout->takeAt(0)) != 0)
                {
                delete child;
                }
                @

                joonhwan at gmail dot com

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  Arukas
                  wrote on 19 Jan 2012, 12:42 last edited by
                  #17

                  I don't agree. I tried many things, and I eventually removed the show. "Here's a link to some example code.":http://dl.dropbox.com/u/481280/layoutDeleter.zip It doesn't matter that I use a QWidget or not, the layout is still not deleted from the GUI.

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    lgeyer
                    wrote on 19 Jan 2012, 14:14 last edited by
                    #18
                    • If a widget is deleted, all of its children are deleted which is the same as a child is deleted, when its parent is deleted.
                    • If a widget A has a layout, and you add widget B to this layout, the layouts parent, A, becomes the new parent for the widget B, not the layout itself.

                    This means in your case, that if you add a widget <code>stupidKid</code> to <code>ui->verticalLayout</code>, <code>ui->verticalLayoutWidget</code> (which was implicitly created by the UI designer to hold <code>verticalLayout</code>, as every layout needs a parent widget) becomes the parent of <code>stupidKid</code>, and <code>ui->verticalLayout</code> becomes the layout manager.

                    QLayout::takeAt() does not return the widgets themselves, it returns a QLayoutItem, which was used by the QVBoxLayout layout manager to manage the widget. If you now delete the QLayoutItem you do not delete the widget as well, because the layout or the QLayoutItem is not the parent of the widget, the layouts parent widget <code>ui->verticalLayoutWidget</code> is.

                    Thus your <code>stupidKit</code> widgets still have a valid parent, thus they have not been deleted and thus they are still shown - they just got their layout manager removed. So for your code to work properly, you will have to delete the widget as well (do not just hide them, this will leak memory).
                    @
                    void MainWindow::removeAll()
                    {
                    QLayoutItem* child;
                    child=ui->verticalLayout->takeAt(0);
                    while(child != 0)
                    {
                    if(child->widget())
                    delete child->widget();

                        delete child;
                        child=ui->verticalLayout->takeAt(0);
                    }
                    

                    }
                    @
                    Be aware that this implemention is limited to layouts which contain only widgets. If you add layouts too, you will have to use a recursive implementation, as shown in my previous post.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      Arukas
                      wrote on 19 Jan 2012, 16:42 last edited by
                      #19

                      Lets see if I understand you correctly. My confusion is that ui->verticalLayoutWidget is the actually parent widget, which is the source of my problems.

                      I got up too early and read your post, and I missed the recursive part. I'll give it a try and see if I can get it to work.

                      -Thanks

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        lgeyer
                        wrote on 19 Jan 2012, 16:59 last edited by
                        #20

                        [quote author="Arukas" date="1326991322"]Lets see if I understand you correctly. My confusion is that ui->verticalLayoutWidget is the actually parent widget, which is the source of my problems. [/quote]

                        Yes, if you add a widget to a layout, the layouts parent becomes the parent for the widget, <code>ui->verticalLayoutWidget</code> in your case.

                        If you want to dig deeper on your own go to KDABs website and fetch "GammaRay":http://www.kdab.com/gammaray, an absolutely great tool when it comes to introspecting and debugging Qt applications.

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          joonhwan
                          wrote on 20 Jan 2012, 01:03 last edited by
                          #21

                          [quote author="Arukas" date="1326976934"]I don't agree. I tried many things, and I eventually removed the show. "Here's a link to some example code.":http://dl.dropbox.com/u/481280/layoutDeleter.zip It doesn't matter that I use a QWidget or not, the layout is still not deleted from the GUI.
                          [/quote]

                          I inspected your code, and that's not actually what I meant.

                          please check "this":http://dl.dropbox.com/u/3699382/layoutDeleter2.zip
                          and be noted that any layout instance will be deleted as soon as place holder widget is gone.

                          And see the difference and wanna hear your review on it.

                          joonhwan at gmail dot com

                          1 Reply Last reply
                          0

                          19/21

                          19 Jan 2012, 16:42

                          • Login

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