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 QScrollArea to layout locks application.
Forum Updated to NodeBB v4.3 + New Features

Adding QScrollArea to layout locks application.

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 168 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I have written a simple test application:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , mpButtonGroupA(nullptr)
        , mpButtonGroupB(nullptr)
        , mpFormLayoutA(nullptr)
        , mpFormLayoutB(nullptr)
        , mpsaA(nullptr)
        , mpsaB(nullptr)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        int intFixedHeight(fontMetrics().height() * 3);
    
        QVBoxLayout* pvbxLayout(new QVBoxLayout);
        QWidget* pContainerA(new QWidget);
        QWidget* pContainerB(new QWidget);
    
        mpsaA = new QScrollArea;
        mpsaA->setWidget(pContainerA);
        mpsaA->setFixedHeight(intFixedHeight);
        mpsaA->setWidgetResizable(true);
        pvbxLayout->addWidget(mpsaA);
    
        mpFormLayoutA = new QFormLayout;
        mpFormLayoutA->setContentsMargins(0,0,0,0);
        mpFormLayoutA->setSpacing(0);
        mpFormLayoutA->setHorizontalSpacing(10);
        pContainerA->setLayout(mpFormLayoutA);
        mpButtonGroupA = new QButtonGroup(pContainerA);
        mpButtonGroupA->setObjectName("Button Group A");
    
        mpsaB = new QScrollArea;
        mpsaB->setWidget(pContainerB);
        mpsaB->setFixedHeight(intFixedHeight);
        mpsaB->setWidgetResizable(true);
        pvbxLayout->addWidget(mpsaB);
    
        mpFormLayoutB = new QFormLayout;
        mpFormLayoutB->setContentsMargins(0,0,0,0);
        mpFormLayoutB->setSpacing(0);
        mpFormLayoutB->setHorizontalSpacing(10);
        pContainerB->setLayout(mpFormLayoutB);
        mpButtonGroupB = new QButtonGroup(pContainerB);
        mpButtonGroupB->setObjectName("Button Group B");
    
        for( int i=1; i<=10; i++ ) {
            QRadioButton* pRadioButton(new QRadioButton(QString("Radio %1").arg(i)));
            if ( i < 6 ) {
                mpButtonGroupA->addButton(pRadioButton);
                mpFormLayoutA->addRow(QString::number(i), pRadioButton);
            } else {
                mpButtonGroupB->addButton(pRadioButton);
                mpFormLayoutB->addRow(QString::number(i), pRadioButton);
            }
            QObject::connect(pRadioButton, &QRadioButton::clicked,
                [pRadioButton](bool blnChecked) {
                    qDebug() << pRadioButton->group() << ":" << pRadioButton->text() << " Checked: " << blnChecked;
                }
            );
        }
        pvbxLayout->addWidget(new QPushButton("HELLO"));    
    
        ui->centralwidget->setLayout(pvbxLayout);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    This works, now based not the above I want to implement in my main application, my layout class:

        class clsQtLayout {
            friend class clsXMLnode;
    
        private:
            clsXMLnode* mpobjNode;
            QScrollArea* mpobjScroller;
    
        public:
            static const char mscszFormLayout[];
            static const char mscszGridLayout[];
            static const char mscszHBoxLayout[];
            static const char mscszVBoxLayout[];
            explicit clsQtLayout(clsXMLnode* pobjNode, const QSize& crszFixed
                                                     , QWidget* pobjParent);
            void addWidget(QWidget* pobjWidget);
            QLayout* pobjLayout();
            QScrollArea* pobjScroller() { return mpobjScroller; }
        };
    

    The implementation:

    /**
     * File:    clsQtLayout.cpp
     * Notes:   Contains implementation of the class clsQtLayout
     * History: 2021/10/23 Created by Simon Platten
     */
    #include <clsQtLayout.h>
    //Static initialisation
    const char clsQtLayout::mscszFormLayout[]   = "QFormLayout";
    const char clsQtLayout::mscszGridLayout[]   = "QGridLayout";
    const char clsQtLayout::mscszHBoxLayout[]   = "QHBoxLayout";
    const char clsQtLayout::mscszVBoxLayout[]   = "QVBoxLayout";
    /**
     * @brief clsQtLayout::clsQtLayout
     * @param pobjNode : Pointer to XML node
     * @param crszFixed : Constant reference to fixed size
     * @param pobjParent : Pointer to parent widget
     */
    clsQtLayout::clsQtLayout(clsXMLnode* pobjNode, const QSize& crszFixed, QWidget* pobjParent)
                    : mpobjNode(pobjNode)
                    , mpobjScroller(nullptr) {
        static const char scszConstructor[] = "clsQtLayout::clsQtLayout";
        Q_ASSERT_X(pobjNode!=nullptr, scszConstructor, "No node supplied!");
        Q_ASSERT_X(pobjParent!=nullptr, scszConstructor, "No parent widget supplied!");
        QString strType(pobjNode->strGetAttribute(clsXMLnode::mscszAttrType)), strName;
        int intFixedHeight, intFixedWidth;
        intFixedHeight = intFixedWidth = 0;
        //Create widget for the layout
        mpobjNode->setWidget(new QWidget);
        //What type of layout?
        if ( strType.compare(clsXMLnode::mscszLayoutForm) == 0 ) {
            mpobjNode->setLayout(new QFormLayout);
            strName = clsQtLayout::mscszFormLayout;
        } else if ( strType.compare(clsXMLnode::mscszLayoutGrid) == 0 ) {
            mpobjNode->setLayout(new QGridLayout);
            strName = clsQtLayout::mscszGridLayout;
        } else if ( strType.compare(clsXMLnode::mscszLayoutHorizontal) == 0 ) {
            mpobjNode->setLayout(new QHBoxLayout);
            intFixedWidth = crszFixed.width();
            strName = clsQtLayout::mscszHBoxLayout;
        } else if ( strType.compare(clsXMLnode::mscszLayoutVertical) == 0 ) {
            mpobjNode->setLayout(new QVBoxLayout);
            intFixedHeight = crszFixed.height();
            strName = clsQtLayout::mscszVBoxLayout;
        }
        QLayout* pobjLayout(mpobjNode->pobjGetLayout());
        Q_ASSERT_X(pobjLayout!=nullptr, scszConstructor, "Layout has not been created!");
        QString strParentName(pobjParent->objectName());
        if ( strParentName.isEmpty() != true ) {
            strName += ", " + pobjParent->objectName();
        }
        pobjLayout->setObjectName(strName);
        if ( intFixedHeight > 0 || intFixedWidth > 0 ) {
            mpobjScroller = new QScrollArea;
            mpobjScroller->setWidget(mpobjNode->pobjGetWidget());
            if ( intFixedHeight > 0 ) {
                mpobjScroller->setFixedHeight(intFixedHeight);
            }
            if ( intFixedWidth > 0 ) {
                mpobjScroller->setFixedWidth(intFixedWidth);
            }
            mpobjScroller->setWidgetResizable(true);
            pobjLayout->addWidget(mpobjScroller);
        }
    }
    /**
     * @brief clsQtLayout::addWidget
     * @param pobjWidget    Pointer to widget to add
     */
    void clsQtLayout::addWidget(QWidget *pobjWidget) {
        if ( pobjWidget != nullptr && mpobjNode != nullptr ) {
            QLayout* pobjLayout(mpobjNode->pobjGetLayout());
            if ( pobjLayout != nullptr ) {
                pobjLayout->addWidget(pobjWidget);
            }
        }
    }
    

    Using the debugger I've single stepped to the line:

    pobjLayout->addWidget(mpobjScroller);
    

    In the clsQtLayout constructor, this doesn't return and hangs the application, no error message is displayed execution just hangs.

    I've looked at the various pointers and everything looks ok, can anyone suggest what I may have done wrong as I've compare the source with the original prototype and cannot see whats wrong.

    [Edit] I've modified the source passing pobjParent to the layouts on creation, no difference, same result, locks up on addWidget.

    Kind Regards,
    Sy

    SPlattenS 1 Reply Last reply
    0
    • SPlattenS SPlatten

      I have written a simple test application:

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
          , mpButtonGroupA(nullptr)
          , mpButtonGroupB(nullptr)
          , mpFormLayoutA(nullptr)
          , mpFormLayoutB(nullptr)
          , mpsaA(nullptr)
          , mpsaB(nullptr)
          , ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
      
          int intFixedHeight(fontMetrics().height() * 3);
      
          QVBoxLayout* pvbxLayout(new QVBoxLayout);
          QWidget* pContainerA(new QWidget);
          QWidget* pContainerB(new QWidget);
      
          mpsaA = new QScrollArea;
          mpsaA->setWidget(pContainerA);
          mpsaA->setFixedHeight(intFixedHeight);
          mpsaA->setWidgetResizable(true);
          pvbxLayout->addWidget(mpsaA);
      
          mpFormLayoutA = new QFormLayout;
          mpFormLayoutA->setContentsMargins(0,0,0,0);
          mpFormLayoutA->setSpacing(0);
          mpFormLayoutA->setHorizontalSpacing(10);
          pContainerA->setLayout(mpFormLayoutA);
          mpButtonGroupA = new QButtonGroup(pContainerA);
          mpButtonGroupA->setObjectName("Button Group A");
      
          mpsaB = new QScrollArea;
          mpsaB->setWidget(pContainerB);
          mpsaB->setFixedHeight(intFixedHeight);
          mpsaB->setWidgetResizable(true);
          pvbxLayout->addWidget(mpsaB);
      
          mpFormLayoutB = new QFormLayout;
          mpFormLayoutB->setContentsMargins(0,0,0,0);
          mpFormLayoutB->setSpacing(0);
          mpFormLayoutB->setHorizontalSpacing(10);
          pContainerB->setLayout(mpFormLayoutB);
          mpButtonGroupB = new QButtonGroup(pContainerB);
          mpButtonGroupB->setObjectName("Button Group B");
      
          for( int i=1; i<=10; i++ ) {
              QRadioButton* pRadioButton(new QRadioButton(QString("Radio %1").arg(i)));
              if ( i < 6 ) {
                  mpButtonGroupA->addButton(pRadioButton);
                  mpFormLayoutA->addRow(QString::number(i), pRadioButton);
              } else {
                  mpButtonGroupB->addButton(pRadioButton);
                  mpFormLayoutB->addRow(QString::number(i), pRadioButton);
              }
              QObject::connect(pRadioButton, &QRadioButton::clicked,
                  [pRadioButton](bool blnChecked) {
                      qDebug() << pRadioButton->group() << ":" << pRadioButton->text() << " Checked: " << blnChecked;
                  }
              );
          }
          pvbxLayout->addWidget(new QPushButton("HELLO"));    
      
          ui->centralwidget->setLayout(pvbxLayout);
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      

      This works, now based not the above I want to implement in my main application, my layout class:

          class clsQtLayout {
              friend class clsXMLnode;
      
          private:
              clsXMLnode* mpobjNode;
              QScrollArea* mpobjScroller;
      
          public:
              static const char mscszFormLayout[];
              static const char mscszGridLayout[];
              static const char mscszHBoxLayout[];
              static const char mscszVBoxLayout[];
              explicit clsQtLayout(clsXMLnode* pobjNode, const QSize& crszFixed
                                                       , QWidget* pobjParent);
              void addWidget(QWidget* pobjWidget);
              QLayout* pobjLayout();
              QScrollArea* pobjScroller() { return mpobjScroller; }
          };
      

      The implementation:

      /**
       * File:    clsQtLayout.cpp
       * Notes:   Contains implementation of the class clsQtLayout
       * History: 2021/10/23 Created by Simon Platten
       */
      #include <clsQtLayout.h>
      //Static initialisation
      const char clsQtLayout::mscszFormLayout[]   = "QFormLayout";
      const char clsQtLayout::mscszGridLayout[]   = "QGridLayout";
      const char clsQtLayout::mscszHBoxLayout[]   = "QHBoxLayout";
      const char clsQtLayout::mscszVBoxLayout[]   = "QVBoxLayout";
      /**
       * @brief clsQtLayout::clsQtLayout
       * @param pobjNode : Pointer to XML node
       * @param crszFixed : Constant reference to fixed size
       * @param pobjParent : Pointer to parent widget
       */
      clsQtLayout::clsQtLayout(clsXMLnode* pobjNode, const QSize& crszFixed, QWidget* pobjParent)
                      : mpobjNode(pobjNode)
                      , mpobjScroller(nullptr) {
          static const char scszConstructor[] = "clsQtLayout::clsQtLayout";
          Q_ASSERT_X(pobjNode!=nullptr, scszConstructor, "No node supplied!");
          Q_ASSERT_X(pobjParent!=nullptr, scszConstructor, "No parent widget supplied!");
          QString strType(pobjNode->strGetAttribute(clsXMLnode::mscszAttrType)), strName;
          int intFixedHeight, intFixedWidth;
          intFixedHeight = intFixedWidth = 0;
          //Create widget for the layout
          mpobjNode->setWidget(new QWidget);
          //What type of layout?
          if ( strType.compare(clsXMLnode::mscszLayoutForm) == 0 ) {
              mpobjNode->setLayout(new QFormLayout);
              strName = clsQtLayout::mscszFormLayout;
          } else if ( strType.compare(clsXMLnode::mscszLayoutGrid) == 0 ) {
              mpobjNode->setLayout(new QGridLayout);
              strName = clsQtLayout::mscszGridLayout;
          } else if ( strType.compare(clsXMLnode::mscszLayoutHorizontal) == 0 ) {
              mpobjNode->setLayout(new QHBoxLayout);
              intFixedWidth = crszFixed.width();
              strName = clsQtLayout::mscszHBoxLayout;
          } else if ( strType.compare(clsXMLnode::mscszLayoutVertical) == 0 ) {
              mpobjNode->setLayout(new QVBoxLayout);
              intFixedHeight = crszFixed.height();
              strName = clsQtLayout::mscszVBoxLayout;
          }
          QLayout* pobjLayout(mpobjNode->pobjGetLayout());
          Q_ASSERT_X(pobjLayout!=nullptr, scszConstructor, "Layout has not been created!");
          QString strParentName(pobjParent->objectName());
          if ( strParentName.isEmpty() != true ) {
              strName += ", " + pobjParent->objectName();
          }
          pobjLayout->setObjectName(strName);
          if ( intFixedHeight > 0 || intFixedWidth > 0 ) {
              mpobjScroller = new QScrollArea;
              mpobjScroller->setWidget(mpobjNode->pobjGetWidget());
              if ( intFixedHeight > 0 ) {
                  mpobjScroller->setFixedHeight(intFixedHeight);
              }
              if ( intFixedWidth > 0 ) {
                  mpobjScroller->setFixedWidth(intFixedWidth);
              }
              mpobjScroller->setWidgetResizable(true);
              pobjLayout->addWidget(mpobjScroller);
          }
      }
      /**
       * @brief clsQtLayout::addWidget
       * @param pobjWidget    Pointer to widget to add
       */
      void clsQtLayout::addWidget(QWidget *pobjWidget) {
          if ( pobjWidget != nullptr && mpobjNode != nullptr ) {
              QLayout* pobjLayout(mpobjNode->pobjGetLayout());
              if ( pobjLayout != nullptr ) {
                  pobjLayout->addWidget(pobjWidget);
              }
          }
      }
      

      Using the debugger I've single stepped to the line:

      pobjLayout->addWidget(mpobjScroller);
      

      In the clsQtLayout constructor, this doesn't return and hangs the application, no error message is displayed execution just hangs.

      I've looked at the various pointers and everything looks ok, can anyone suggest what I may have done wrong as I've compare the source with the original prototype and cannot see whats wrong.

      [Edit] I've modified the source passing pobjParent to the layouts on creation, no difference, same result, locks up on addWidget.

      SPlattenS Offline
      SPlattenS Offline
      SPlatten
      wrote on last edited by
      #2

      @SPlatten , I think I found the issue, at least it doesn't lock up now, still not the results I wanted in that the content I'm adding to the layout isn't inside the layout:

      /**
       * File:    clsQtLayout.cpp
       * Notes:   Contains implementation of the class clsQtLayout
       * History: 2021/10/23 Created by Simon Platten
       */
      #include <clsQtLayout.h>
      //Static initialisation
      const char clsQtLayout::mscszFormLayout[]   = "QFormLayout";
      const char clsQtLayout::mscszGridLayout[]   = "QGridLayout";
      const char clsQtLayout::mscszHBoxLayout[]   = "QHBoxLayout";
      const char clsQtLayout::mscszVBoxLayout[]   = "QVBoxLayout";
      /**
       * @brief clsQtLayout::clsQtLayout
       * @param pobjNode : Pointer to XML node
       * @param crszFixed : Constant reference to fixed size
       * @param pobjParent : Pointer to parent widget
       */
      clsQtLayout::clsQtLayout(clsXMLnode* pobjNode, const QSize& crszFixed, QWidget* pobjParent)
                      : mpobjNode(pobjNode)
                      , mpobjScroller(nullptr) {
          static const char scszConstructor[] = "clsQtLayout::clsQtLayout";
          Q_ASSERT_X(pobjNode!=nullptr, scszConstructor, "No node supplied!");
          Q_ASSERT_X(pobjParent!=nullptr, scszConstructor, "No parent widget supplied!");
          QString strType(pobjNode->strGetAttribute(clsXMLnode::mscszAttrType));
          int intFixedHeight, intFixedWidth;
          intFixedHeight = crszFixed.height();
          intFixedWidth = crszFixed.width();
          //Create widget for the layout
          mpobjNode->setWidget(new QWidget);
          //What type of layout?
          if ( strType.compare(clsXMLnode::mscszLayoutForm) == 0 ) {
              mpobjNode->setLayout(new QFormLayout(pobjParent));
          } else if ( strType.compare(clsXMLnode::mscszLayoutGrid) == 0 ) {
              mpobjNode->setLayout(new QGridLayout(pobjParent));
          } else if ( strType.compare(clsXMLnode::mscszLayoutHorizontal) == 0 ) {
              mpobjNode->setLayout(new QHBoxLayout(pobjParent));
          } else if ( strType.compare(clsXMLnode::mscszLayoutVertical) == 0 ) {
              mpobjNode->setLayout(new QVBoxLayout(pobjParent));
          } else {
          //No valid layout supplied
              Q_ASSERT_X(nullptr, scszConstructor, "Layout has not been created!");
              return;
          }
          //Get the parent layout
          clsXMLnode* pobjParentNode(mpobjNode->pobjGetParent());
          QLayout* pobjLayout(pobjParentNode->pobjGetLayout());
          if ( intFixedHeight > 0 || intFixedWidth > 0 ) {
              mpobjScroller = new QScrollArea;
              mpobjScroller->setWidget(mpobjNode->pobjGetWidget());
              if ( intFixedHeight > 0 ) {
                  mpobjScroller->setFixedHeight(intFixedHeight);
              }
              if ( intFixedWidth > 0 ) {
                  mpobjScroller->setFixedWidth(intFixedWidth);
              }
              mpobjScroller->setWidgetResizable(true);
              pobjLayout->addWidget(mpobjScroller);
          }
      }
      /**
       * @brief clsQtLayout::addWidget
       * @param pobjWidget    Pointer to widget to add
       */
      void clsQtLayout::addWidget(QWidget *pobjWidget) {
          if ( pobjWidget != nullptr && mpobjNode != nullptr ) {
              QLayout* pobjLayout(mpobjNode->pobjGetLayout());
              if ( pobjLayout != nullptr ) {
                  pobjLayout->addWidget(pobjWidget);
              }
          }
      }
      

      Kind Regards,
      Sy

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

        Seems you are engaged in a loop.
        Run the debugger and when it's hang, interrupt the debugger to see the stack frame.

        [Edit] too late :)

        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