Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved QVBoxLayout just stacking widgets on top of each other

    General and Desktop
    qscrollarea qvboxlayout qwidgetlist widget list
    2
    3
    1014
    Loading More Posts
    • 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.
    • E
      Erika_Butler last edited by Erika_Butler

      I have a class named VerticalWidgetList, which is meant to use a QVBoxLayout to display widgets added to it in a list from top to bottom in the order the widgets were added. I'm having a problem with it, though, as when I add widgets using addWidget(), it instead seems to stack the widgets on top of each other. Here is the source code for the class. Am I setting this up right?

      verticalwidgetlist.h

      #ifndef VERTICALWIDGETLIST_H
      #define VERTICALWIDGETLIST_H
      
      #include <QScrollArea>
      #include <QVBoxLayout>
      #include <QWidgetList>
      
      class VerticalWidgetList : public QScrollArea {
          Q_OBJECT
      public:
          explicit VerticalWidgetList(QWidget *parent = nullptr);
      
          bool addWidget(QWidget *child);
          void clearWidgets();
          bool insertWidget(int index, QWidget *child);
          bool removeWidget(int index);
          bool removeWidgetAt(QWidget *child);
          QWidget *takeWidget(int index);
          int widgetAt(QWidget *child) const;
      
      private:
          QWidget *m_central;
          QVBoxLayout *m_layout;
          QWidgetList m_list;
      
      };
      
      #endif // VERTICALWIDGETLIST_H
      
      

      verticalwidgetlist.cpp

      #include "verticalwidgetlist.h"
      
      VerticalWidgetList::VerticalWidgetList(QWidget *parent)
          : QScrollArea(parent)
          , m_central(new QWidget)
          , m_layout(new QVBoxLayout(m_central))
          , m_list()
      {
          setWidget(m_central);
          setWidgetResizable(true);
      }
      
      bool VerticalWidgetList::addWidget(QWidget *child) {
          if(child == nullptr)
              return false;
          m_layout->addWidget(child);
          m_list.append(child);
          child->setParent(this);
          return true;
      }
      
      void VerticalWidgetList::clearWidgets() {
          while(m_list.count()) {
              QWidget *widget = m_list.takeAt(0);
              m_layout->removeWidget(widget);
          }
      }
      
      bool VerticalWidgetList::insertWidget(int index, QWidget *child) {
          if(index < 0 || index > m_list.count())
              return false;
          if(child == nullptr)
              return false;
          m_layout->insertWidget(index, child);
          m_list.insert(index, child);
          child->setParent(this);
          return true;
      }
      
      bool VerticalWidgetList::removeWidget(int index) {
          if(index < 0 || index >= m_list.count())
              return false;
          QWidget *widget = m_list.takeAt(index);
          m_layout->removeWidget(widget);
          delete widget;
          return true;
      }
      
      bool VerticalWidgetList::removeWidgetAt(QWidget *child) {
          if(child == nullptr)
              return false;
          m_layout->removeWidget(child);
          int index = widgetAt(child);
          m_list.removeAt(index);
          delete child;
          return true;
      }
      
      QWidget *VerticalWidgetList::takeWidget(int index) {
          if(index < 0 || index >= m_list.count())
              return nullptr;
          QWidget *widget = m_list.takeAt(index);
          m_layout->removeWidget(widget);
          widget->setParent(nullptr);
          return widget;
      }
      
      int VerticalWidgetList::widgetAt(QWidget *child) const {
          if(child == nullptr)
              return -1;
          return m_list.indexOf(child);
      }
      
      
      jsulm 1 Reply Last reply Reply Quote 0
      • E
        Erika_Butler @jsulm last edited by Erika_Butler

        @jsulm Fortunately, I just solved it. I should not have specified the VerticalWidgetList class as the parent of the widgets added. Apparently, when you add it to the layout, the widgets added get some sort of other parent class. I still nullptr out the widget in the takeWidget() function, however, as control of it should pass to the function receiving the return value. When I got rid of setting the parent in the addWidget() and insertWidget() functions, it now works properly.

        I do wonder if I should still delete the child widget in removeWidget() and removeWidgetAt() after removing it from the layout. Or do I need to set the parent to nullptr before deleting it? When my program used clearWidgets(), which calls removeWidget(), there was no problem.

        It works now!

        This is the source code now:

        verticalwidgetlist.h

        #ifndef VERTICALWIDGETLIST_H
        #define VERTICALWIDGETLIST_H
        
        #include <QScrollArea>
        #include <QVBoxLayout>
        #include <QWidgetList>
        
        class VerticalWidgetList : public QScrollArea {
            Q_OBJECT
        public:
            explicit VerticalWidgetList(QWidget *parent = nullptr);
        
            bool addWidget(QWidget *child);
            void clearWidgets();
            bool insertWidget(int index, QWidget *child);
            bool removeWidget(QWidget *child;
            bool removeWidgetAt(int index);
            QWidget *takeWidget(int index);
            int widgetAt(QWidget *child) const;
        
        private:
            QWidget *m_central;
            QVBoxLayout *m_layout;
            QWidgetList m_list;
        
        };
        
        #endif // VERTICALWIDGETLIST_H
        
        

        verticalwidgetlist.cpp

        #include "verticalwidgetlist.h"
        
        VerticalWidgetList::VerticalWidgetList(QWidget *parent)
            : QScrollArea(parent)
            , m_central(new QWidget)
            , m_layout(new QVBoxLayout(m_central))
            , m_list()
        {
            setWidget(m_central);
            setWidgetResizable(true);
        }
        
        bool VerticalWidgetList::addWidget(QWidget *child) {
            if(child == nullptr)
                return false;
            m_layout->addWidget(child);
            m_list.append(child);
            return true;
        }
        
        void VerticalWidgetList::clearWidgets() {
            while(m_list.count()) {
                QWidget *widget = m_list[0];
                removeWidget(widget);
            }
        }
        
        bool VerticalWidgetList::insertWidget(int index, QWidget *child) {
            if(index < 0 || index > m_list.count())
                return false;
            if(child == nullptr)
                return false;
            m_layout->insertWidget(index, child);
            m_list.insert(index, child);
            return true;
        }
        
        bool VerticalWidgetList::removeWidget(QWidget *child) {
            if(child == nullptr)
                return false;
            m_layout->removeWidget(child);
            int index = widgetAt(child);
            m_list.removeAt(index);
            delete child;
            return true;
        }
        
        bool VerticalWidgetList::removeWidgetAt(int index) {
            if(index < 0 || index >= m_list.count())
                return false;
            QWidget *widget = m_list.takeAt(index);
            m_layout->removeWidget(widget);
            delete widget;
            return true;
        }
        
        QWidget *VerticalWidgetList::takeWidget(int index) {
            if(index < 0 || index >= m_list.count())
                return nullptr;
            QWidget *widget = m_list.takeAt(index);
            m_layout->removeWidget(widget);
            widget->setParent(nullptr);
            return widget;
        }
        
        int VerticalWidgetList::widgetAt(QWidget *child) const {
            if(child == nullptr)
                return -1;
            return m_list.indexOf(child);
        }
        
        

        EDIT: If anyone tried the source code up until this point, in this post, try again. I was rearranging removeWidget() and removeWidgetAt(), which I realized were mismatched in terms of their parameters. It's good now!

        1 Reply Last reply Reply Quote 0
        • jsulm
          jsulm Lifetime Qt Champion @Erika_Butler last edited by

          @Erika_Butler Then use https://doc.qt.io/qt-5/qboxlayout.html#insertWidget and specify the index

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          E 1 Reply Last reply Reply Quote 0
          • E
            Erika_Butler @jsulm last edited by Erika_Butler

            @jsulm Fortunately, I just solved it. I should not have specified the VerticalWidgetList class as the parent of the widgets added. Apparently, when you add it to the layout, the widgets added get some sort of other parent class. I still nullptr out the widget in the takeWidget() function, however, as control of it should pass to the function receiving the return value. When I got rid of setting the parent in the addWidget() and insertWidget() functions, it now works properly.

            I do wonder if I should still delete the child widget in removeWidget() and removeWidgetAt() after removing it from the layout. Or do I need to set the parent to nullptr before deleting it? When my program used clearWidgets(), which calls removeWidget(), there was no problem.

            It works now!

            This is the source code now:

            verticalwidgetlist.h

            #ifndef VERTICALWIDGETLIST_H
            #define VERTICALWIDGETLIST_H
            
            #include <QScrollArea>
            #include <QVBoxLayout>
            #include <QWidgetList>
            
            class VerticalWidgetList : public QScrollArea {
                Q_OBJECT
            public:
                explicit VerticalWidgetList(QWidget *parent = nullptr);
            
                bool addWidget(QWidget *child);
                void clearWidgets();
                bool insertWidget(int index, QWidget *child);
                bool removeWidget(QWidget *child;
                bool removeWidgetAt(int index);
                QWidget *takeWidget(int index);
                int widgetAt(QWidget *child) const;
            
            private:
                QWidget *m_central;
                QVBoxLayout *m_layout;
                QWidgetList m_list;
            
            };
            
            #endif // VERTICALWIDGETLIST_H
            
            

            verticalwidgetlist.cpp

            #include "verticalwidgetlist.h"
            
            VerticalWidgetList::VerticalWidgetList(QWidget *parent)
                : QScrollArea(parent)
                , m_central(new QWidget)
                , m_layout(new QVBoxLayout(m_central))
                , m_list()
            {
                setWidget(m_central);
                setWidgetResizable(true);
            }
            
            bool VerticalWidgetList::addWidget(QWidget *child) {
                if(child == nullptr)
                    return false;
                m_layout->addWidget(child);
                m_list.append(child);
                return true;
            }
            
            void VerticalWidgetList::clearWidgets() {
                while(m_list.count()) {
                    QWidget *widget = m_list[0];
                    removeWidget(widget);
                }
            }
            
            bool VerticalWidgetList::insertWidget(int index, QWidget *child) {
                if(index < 0 || index > m_list.count())
                    return false;
                if(child == nullptr)
                    return false;
                m_layout->insertWidget(index, child);
                m_list.insert(index, child);
                return true;
            }
            
            bool VerticalWidgetList::removeWidget(QWidget *child) {
                if(child == nullptr)
                    return false;
                m_layout->removeWidget(child);
                int index = widgetAt(child);
                m_list.removeAt(index);
                delete child;
                return true;
            }
            
            bool VerticalWidgetList::removeWidgetAt(int index) {
                if(index < 0 || index >= m_list.count())
                    return false;
                QWidget *widget = m_list.takeAt(index);
                m_layout->removeWidget(widget);
                delete widget;
                return true;
            }
            
            QWidget *VerticalWidgetList::takeWidget(int index) {
                if(index < 0 || index >= m_list.count())
                    return nullptr;
                QWidget *widget = m_list.takeAt(index);
                m_layout->removeWidget(widget);
                widget->setParent(nullptr);
                return widget;
            }
            
            int VerticalWidgetList::widgetAt(QWidget *child) const {
                if(child == nullptr)
                    return -1;
                return m_list.indexOf(child);
            }
            
            

            EDIT: If anyone tried the source code up until this point, in this post, try again. I was rearranging removeWidget() and removeWidgetAt(), which I realized were mismatched in terms of their parameters. It's good now!

            1 Reply Last reply Reply Quote 0
            • First post
              Last post