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. Deleting data from a QScrollArea
Forum Updated to NodeBB v4.3 + New Features

Deleting data from a QScrollArea

Scheduled Pinned Locked Moved Solved General and Desktop
qscrollarea
16 Posts 2 Posters 10.2k 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.
  • M Offline
    M Offline
    mar0029
    wrote on last edited by
    #1

    Hello!

    I am having some trouble removing data from a QScrollArea. When I load data into my GUI, I can school and everything is fine. When I load another set of data, however, my GUI adjusts it's scroll area to match that of the new file but doesn't get rid of the old data. It just lays the new data on top of the old data, creating a neat effect but unwanted.

    Here is my code:

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    
    scrollArea = new QScrollArea();
    scrollArea->setBackgroundRole(QPalette::Light);
    scrollArea->setWidgetResizable(true);
    
    mainVbox = new QVBoxLayout();
    
    myWidget = new QWidget();
    myWidget->setLayout(mainVbox);
    
    scrollArea->setWidget(myWidget);
    
    setCentralWidget(scrollArea);
    }
    

    So I create my QScrollArea, change some of it's attributes.
    Next I create a widget to hold my main layout.
    Then I set the widget of scrollArea to myWidget.
    Lastly, I set the central widget to scrollArea.

    What I add to the mainLayout is another layout that contains three widgets. And I add a LOT of these layouts to the main layout. Here is that code with the code I thought would delete the old layouts

    ...
    ...
    QLayoutItem* child;
    while((child = myWidget->layout()->layout()->takeAt(0)) != NULL)
    {
        delete child->layout()->widget();   //This doesn't work but it doesn't break anything...
    }
    
    
    for(int counter = 0; counter < orderQ.size(); counter++)
    {
        subHbox = new QHboxLayout;
        
        if(orderQ.at(counter) == 0)
            {
                Qlabel *label = new QLabel();
                ...
                ...
                mainVbox->addLayout(subHbox);
            }
        else if(...)
        { 
            ...
            mainVbox->addLayout(subHbox);
            ...
        }
    

    Any help or ideas would be greatly appreciated.

    Thank you!!

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      I was wondering why you cannot just delete
      myWidget as that would/should delete all childs also.
      Then make new "myWidget" and fill it again.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mar0029
        wrote on last edited by mar0029
        #3

        Thank you for your reply!

        I tried deleting myWidget and no matter what I did, it crashed every time. But that got me thinking of other ways to approach this. So I did some more thinking and searching, and found in the docs this.

        I tried

        QList<QLayout *> allSubLayouts = mainVbox->findChildren<QLayout *>();
        if(!allSubLayouts.empty())
        {
            int size = allSubLayouts.size();
            for(int i = 0; i < size; i++)
            {
               delete allSubLayouts.at(i);
            }
        }
        

        that produced no results but maybe just deleting the layout only removes the layout. So I tried deleting the widgets in those layouts before deleting the layouts.

        if(!allSubLayouts.empty())
            {
            int size = allSubLayouts.size();
            QLayoutItem *child;
        
            qDebug() << "***************The layout list was not empty" ;
            for(int i = 0; i < size; i++)
            {
                while((child = allSubLayouts.at(i)->takeAt(0)) != 0)
                {
                    qDebug() << "deleting CHILD " << child;
                    delete child;
                }
                qDebug() << "deleting layout " << i << " that has memory address " << allSubLayouts.at(i);
                delete allSubLayouts.at(i);
            }
            mainVbox->update();
            myWidget->update();
        }
        

        As you can see I also tried updating the main layout as well as the widget to no avail. The debug printout says that it is making it into the loop and accessing the correct number of widgets and layouts. I'm just not sure of what to do right now.

        1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @mar0029 said:
          ok, its hard to visualize what u put in to what ;)

          Have you tried making a brand version and simply replace it ?
          scrollArea->setWidget(myWidgetNo2);

          M 1 Reply Last reply
          0
          • mrjjM mrjj

            @mar0029 said:
            ok, its hard to visualize what u put in to what ;)

            Have you tried making a brand version and simply replace it ?
            scrollArea->setWidget(myWidgetNo2);

            M Offline
            M Offline
            mar0029
            wrote on last edited by
            #5

            @mrjj I made a diagram as to what I've created. I'm creating a lot of the QHBoxLayouts within QVBoxLayout.

            mrjjM 1 Reply Last reply
            1
            • M mar0029

              @mrjj I made a diagram as to what I've created. I'm creating a lot of the QHBoxLayouts within QVBoxLayout.

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by mrjj
              #6

              @mar0029
              That is super.
              So its the "red" ones you are trying to replace?

              Also, can u just replace Widget holding all the reds,?
              or you do u need to keep some of them?

              M 1 Reply Last reply
              0
              • mrjjM mrjj

                @mar0029
                That is super.
                So its the "red" ones you are trying to replace?

                Also, can u just replace Widget holding all the reds,?
                or you do u need to keep some of them?

                M Offline
                M Offline
                mar0029
                wrote on last edited by
                #7

                @mrjj Thank you! I used a ruler and everything!

                I would like to keep everything up to the red a.k.a. my QVBoxLayout
                What happens to all of the QHboxLayout and all the widgets within those Layouts, I don't care.

                1 Reply Last reply
                0
                • mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hmm.
                  Ok. I was kinda planning
                  to just create new widget with a boxlayout and call
                  setWidget on ScrollArea.
                  But u say this crashes?

                  M 1 Reply Last reply
                  0
                  • mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by mrjj
                    #9

                    Hi again
                    i made same layout in designer
                    I kill them this way

                    
                    void MainWindow::on_btremove_released() {
                    
                      QList<QWidget*> allSubLayouts = ui->innerwidget->findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
                      int size = allSubLayouts.size();
                      // take all out
                      while (( ui->innerwidget->layout()->takeAt(0)) != 0)
                        // killem
                        for(int i = 0; i < size; i++) {
                          qDebug() << allSubLayouts[i]->metaObject()->className();
                          delete allSubLayouts[i];
                    
                        }
                    
                    
                    }
                    
                    

                    U can check your self.
                    https://www.dropbox.com/s/auivviiv8tv7jfw/myscroll.zip?dl=0
                    should be the same you want if i read ur fine drawing correct :)
                    Note the Qt::FindDirectChildrenOnly flag!

                    M 1 Reply Last reply
                    0
                    • mrjjM mrjj

                      Hmm.
                      Ok. I was kinda planning
                      to just create new widget with a boxlayout and call
                      setWidget on ScrollArea.
                      But u say this crashes?

                      M Offline
                      M Offline
                      mar0029
                      wrote on last edited by
                      #10

                      @mrjj
                      I don't want to delete my QWidget because I would have to dynamically create a new one each time I loaded a new file and I really don't want to deal with that.

                      I'm making some progress with this:

                          while((child = mainVbox->layout()->takeAt(0)) != 0)
                              {
                              delete child;
                              }
                      

                      but in the documentation it says that when I delete a layout, I have to delete the widgets separately.
                      So I'm trying to make a list of the widgets found within the sublayout and then delete from there but it's not working.

                      1 Reply Last reply
                      0
                      • mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Did u try the sample?
                        It leaves the QWidget and layout but kills all it members.

                        M 1 Reply Last reply
                        0
                        • mrjjM mrjj

                          Hi again
                          i made same layout in designer
                          I kill them this way

                          
                          void MainWindow::on_btremove_released() {
                          
                            QList<QWidget*> allSubLayouts = ui->innerwidget->findChildren<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
                            int size = allSubLayouts.size();
                            // take all out
                            while (( ui->innerwidget->layout()->takeAt(0)) != 0)
                              // killem
                              for(int i = 0; i < size; i++) {
                                qDebug() << allSubLayouts[i]->metaObject()->className();
                                delete allSubLayouts[i];
                          
                              }
                          
                          
                          }
                          
                          

                          U can check your self.
                          https://www.dropbox.com/s/auivviiv8tv7jfw/myscroll.zip?dl=0
                          should be the same you want if i read ur fine drawing correct :)
                          Note the Qt::FindDirectChildrenOnly flag!

                          M Offline
                          M Offline
                          mar0029
                          wrote on last edited by
                          #12

                          @mrjj oh my where did you find that flag? How did you know you could do ui->innerWidget->findChildren<QWidget*>(String(), Qt::FindDirectChildrenOnly); ??

                          1 Reply Last reply
                          0
                          • mrjjM mrjj

                            Did u try the sample?
                            It leaves the QWidget and layout but kills all it members.

                            M Offline
                            M Offline
                            mar0029
                            wrote on last edited by
                            #13

                            @mrjj Thank you for your help. I am unable to get it to work right now but I can see this achieving the goal. I will come back to it later today/tomorrow.

                            Thanks again!

                            1 Reply Last reply
                            0
                            • mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              Hi
                              In the documentation for findChildren. I went looking as your
                              drawing made it very clear what u wanted. (kill all inner widgets)

                              So If you do it for your Widget (myWidget), it should do the same.
                              ( i hope :)

                              you are welcome. I hope u get it to work.

                              M 1 Reply Last reply
                              0
                              • mrjjM mrjj

                                Hi
                                In the documentation for findChildren. I went looking as your
                                drawing made it very clear what u wanted. (kill all inner widgets)

                                So If you do it for your Widget (myWidget), it should do the same.
                                ( i hope :)

                                you are welcome. I hope u get it to work.

                                M Offline
                                M Offline
                                mar0029
                                wrote on last edited by
                                #15

                                @mrjj
                                So here is what I've ended up doing.

                                I had been able to get a QList of the layouts in the main layout like so

                                 QList<QLayout *> allSubLayouts = mainVbox->findChildren<QLayout *>();
                                

                                So I checked if that list was empty or not, basically seeing if it was the first time to use the program.

                                if(!allSubLayouts.empty())
                                {
                                
                                    int size = allSubLayouts.size();
                                    for(int i = 0; i < size; i ++)
                                    {
                                        qDebug() << "this is what is at allSublayouts.at("<<i<<") " << allSubLayouts.at(i);
                                
                                
                                        for(int j = 0; j < allSubLayouts.at(i)->count(); ++j)
                                        {
                                            QWidget *w = allSubLayouts.at(i)->itemAt(j)->widget();
                                            if(w != NULL)
                                            {
                                                w->setVisible(false);
                                            }
                                        }
                                    }
                                }
                                

                                Since I knew that there were layouts available, instead of using findChildren() I used allSubLayouts.at(i)->*itemAt*(j)->*widget*();

                                While this solves my problem of widgets and layouts overlapping in MainWindow, I don't know if it will cause a memory leak or will use up too much memory, since I'm not deleting any widgets/layouts.

                                1 Reply Last reply
                                0
                                • mrjjM Offline
                                  mrjjM Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on last edited by mrjj
                                  #16

                                  Hi

                                  "allSubLayouts.at(i)->*itemAt*(j)->*widget*();"
                                  

                                  made my brain hurt :)
                                  Well since u are not deleting any widgets, u will use more and more memory,
                                  but since they are still owned by layout, it will be free when application ends.

                                  1 Reply Last reply
                                  1

                                  • Login

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