Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to programmatically add widgets to a window to resize?



  • I want to create a window with widgets, creating the window is easy enough, adding widgets to the window is also easily done.

    When the window is resized I want the widgets contained in the window to also resize, is there a way to achieve this using the framework available in Qt?



  • Solved:

    /**
     * @brief clsXMLnode::resize
     * @param pszDeltas : Pointer to pszDeltas to apply
     */
    void clsXMLnode::resize(QSize* pszDeltas) {
        Q_ASSERT_X(pszDeltas!=nullptr, "clsXMLnode::resize", "pszDeltas is null!");
    
        if ( mpobjWidget == nullptr
        || clsXMLnode::mscslstNodesThatCanBeVisible.contains(mstrName) != true
        || (pszDeltas->height() < 0 && pszDeltas->width() < 0) ) {
    //Not ready yet, do nothing!
            return;
        }
        if ( mstrName.compare(clsXMLnode::mscszNodeWindow) != 0 ) {
    //Get the parent of this node
            QWidget* pobjParent = mpobjWidget->parentWidget();
    
            if ( pobjParent == nullptr ) {
                return;
            }
    //Extract dimensions of the parent widget and convert to doubles
            double dblHeight = static_cast<double>(pobjParent->height())
                  ,dblWidth = static_cast<double>(pobjParent->width());
    //Create a copy of the current size
            QSize szCurrent(mpobjWidget->size()), szNew(szCurrent);
    //Create a copy of the current position
            QPoint ptCurrent(mpobjWidget->pos()), ptNew(ptCurrent);
    //Is this node's height percentage based?
            QString strHeight = strGetAttr(clsXMLnode::mscszAttrHeight);
            int intPercent;
    
            if ( strHeight.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strHeight.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setHeight(static_cast<int>((dblHeight * (strHeight.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is this node's width percentage based?
            QString strWidth = strGetAttr(clsXMLnode::mscszAttrWidth);
    
            if ( strWidth.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strWidth.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setWidth(static_cast<int>((dblWidth * (strWidth.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the horizontal position percentage based?
            QString strX = strGetAttr(clsXMLnode::mscszAttrX);
    
            if ( strX.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strX.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setX(static_cast<int>((dblWidth * (strX.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the vertical position percentage based?
            QString strY = strGetAttr(clsXMLnode::mscszAttrY);
    
            if ( strY.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strY.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setY(static_cast<int>((dblHeight * (strY.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Set window geometry
            if ( szCurrent != szNew || ptCurrent != ptNew ) {
                QRect rctGeom(ptNew, szNew);
                mpobjWidget->setGeometry(rctGeom);
            }
        }
    //Get all child nodes
        lstOfNodes lstChildren = lstGetChildNodes();
        foreach( clsXMLnode* pobjChild, lstChildren ) {
    //Does this child have any children?
            pobjChild->resize(pszDeltas);
        }
    }
    


  • Using layouts, or resize them manually in the resizeEvent of the window.



  • @Bonnie , thank you, I tried resizing manually using the resizeEvent, but I'm obviously doing something wrong, the top widget was resizing find, but child widgets did not follow correctly.

    Is there any tutorials or examples on using a layout? I want to be able to position the widgets anywhere in the window.



  • Everything can be found from the doc: https://doc.qt.io/qt-5/layout.html
    But depending on what you want, the predefined layout classes may be not flexible enough.
    Sometimes it is simplier to resize in the resizeEvent.



  • @Bonnie, like I said I tried that, but something is wrong.



  • @SPlatten I got that. But I don't know what you want and what you had done.
    So I was just trying to explain that the predefined classes might not be able to meet your requirements.



  • Here is my work so far:

    bool clsXMLnode::eventFilter(QObject* pobjObject, QEvent* pobjEvent) {
        if ( pobjEvent->type() == QEvent::Resize ) {
    //Get the event information
            QResizeEvent* pobjResize = static_cast<QResizeEvent*>(pobjEvent);
            QWidget* pobjWidget = static_cast<QWidget*>(pobjObject);
            QString strID = pobjWidget->accessibleName();
    
            if ( strID.isEmpty() != true ) {
                clsXMLnode* pobjNode = clsXMLnode::pobjGetNodeById(strID);
    
                if ( pobjNode != nullptr ) {
    //Work out deltas
                    QSize szNew = pobjResize->size(), szOld = pobjResize->oldSize();
                    QSize szDeltas(szNew.width() - szOld.width()
                                  ,szNew.height() - szOld.height());
                    pobjNode->resize(nullptr, &szDeltas);
                }
            }
        }
        return QObject::eventFilter(pobjObject, pobjEvent);
    }
    

    pobjNode in the above is the window.

    void clsXMLnode::resize(QSize* pszWindow, QSize* pszDeltas) {
        Q_ASSERT_X(pszDeltas!=nullptr, "clsXMLnode::resize", "pszDeltas is null!");
    
        if ( mpobjWidget == nullptr
        || clsXMLnode::mscslstNodesThatCanBeVisible.contains(mstrName) != true
        || (pszDeltas->height() < 0 && pszDeltas->width() < 0) ) {
    //Not ready yet, do nothing!
            return;
        }
        QSize szWindow;
    
        if ( mstrName.compare(clsXMLnode::mscszNodeWindow) == 0 ) {
            szWindow = mpobjWidget->size();
    //Apply the deltas to the window
            szWindow += *pszDeltas;
        } else if ( pszWindow != nullptr ) {
    //Copy the window dimensions which already have the deltas applied
            szWindow = *pszWindow;
    //Extract window dimensions and convert to doubles
            double dblHeight = static_cast<double>(szWindow.height())
                  ,dblWidth = static_cast<double>(szWindow.width());
    //Create a copy of the current size
            QSize szCurrent(mpobjWidget->size()), szNew(szCurrent);
    //Create a copy of the current position
            QPoint ptCurrent(mpobjWidget->pos()), ptNew(ptCurrent);
    //Is this node's height percentage based?
            QString strHeight = strGetAttr(clsXMLnode::mscszAttrHeight);
            int intPercent;
    
            if ( strHeight.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strHeight.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setHeight(static_cast<int>((dblHeight * (strHeight.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is this node's width percentage based?
            QString strWidth = strGetAttr(clsXMLnode::mscszAttrWidth);
    
            if ( strWidth.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strWidth.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setWidth(static_cast<int>((dblWidth * (strWidth.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the horizontal position percentage based?
            QString strX = strGetAttr(clsXMLnode::mscszAttrX);
    
            if ( strX.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strX.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setX(static_cast<int>((dblWidth * (strX.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the vertical position percentage based?
            QString strY = strGetAttr(clsXMLnode::mscszAttrY);
    
            if ( strY.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strY.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setY(static_cast<int>((dblHeight * (strY.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Set window geometry
            if ( szCurrent != szNew || ptCurrent != ptNew ) {
                QRect rctGeom(ptNew, szNew);
                mpobjWidget->setGeometry(rctGeom);
            }
        }
    //Get all child nodes
        lstOfNodes lstChildren = lstGetChildNodes();
        foreach( clsXMLnode* pobjChild, lstChildren ) {
    //Does this child have any children?
            pobjChild->resize(&szWindow, pszDeltas);
        }
    }
    

    Something is not quite right in my example here is the XML that I use to test:

    <window id="win1" 
    	frameless="false" 
    	fullscreen="false" 
    	modal="true" 
    	x="25%" y="10%" width="300px" height="30%"
    	properties="color: #000000;							
    	            modal:true;
    	         maximize:false;
    		   minmax:false;
    	   	 minimize:false;"
    	resizeable="true" 
    	title="win1:Hello World">
    	<frame id="frm1" x="10%" y="180" width="80%" height="100" 
    	       properties="QFrame {background-color: #e9efef;
    		                   background-image: url('meshtile_4x4.png');
                                                 border: 2px solid #cccccc;
                                 border-top-left-radius: 8px;
                                border-top-right-radius: 8px;
                              border-bottom-left-radius: 8px;
                             border-bottom-right-radius: 8px;}">
    		<button id="btn1" x="12" y="12" width="50%" height="50%"
      			properties="QPushButton {background-color: #4cb9b3;
                                                      border: 1px solid #3faca6;
                                      border-top-left-radius: 0px;
                                     border-top-right-radius: 8px;
                                   border-bottom-left-radius: 8px;
                                  border-bottom-right-radius: 8px;
                                                       color: #ffffff;
                                                     padding: 1px 18px 1px 3px;
                                                   min-width: 6em}"
    			shadow="3 3 8 #77000000" checkable="true">						
    		        <state value="off" text="Off"/>
    			<state value="on" text="On"/>				
    			<signal name="pbtnClicked">
    			    <subscriber sid="win1:title" script="simon2.js@clicked"/>
    			</signal>	
    		</button>
    	</frame>
    </window>
    

    For some reason the vertical height of the child nodes is changing.



  • Solved:

    /**
     * @brief clsXMLnode::resize
     * @param pszDeltas : Pointer to pszDeltas to apply
     */
    void clsXMLnode::resize(QSize* pszDeltas) {
        Q_ASSERT_X(pszDeltas!=nullptr, "clsXMLnode::resize", "pszDeltas is null!");
    
        if ( mpobjWidget == nullptr
        || clsXMLnode::mscslstNodesThatCanBeVisible.contains(mstrName) != true
        || (pszDeltas->height() < 0 && pszDeltas->width() < 0) ) {
    //Not ready yet, do nothing!
            return;
        }
        if ( mstrName.compare(clsXMLnode::mscszNodeWindow) != 0 ) {
    //Get the parent of this node
            QWidget* pobjParent = mpobjWidget->parentWidget();
    
            if ( pobjParent == nullptr ) {
                return;
            }
    //Extract dimensions of the parent widget and convert to doubles
            double dblHeight = static_cast<double>(pobjParent->height())
                  ,dblWidth = static_cast<double>(pobjParent->width());
    //Create a copy of the current size
            QSize szCurrent(mpobjWidget->size()), szNew(szCurrent);
    //Create a copy of the current position
            QPoint ptCurrent(mpobjWidget->pos()), ptNew(ptCurrent);
    //Is this node's height percentage based?
            QString strHeight = strGetAttr(clsXMLnode::mscszAttrHeight);
            int intPercent;
    
            if ( strHeight.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strHeight.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setHeight(static_cast<int>((dblHeight * (strHeight.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is this node's width percentage based?
            QString strWidth = strGetAttr(clsXMLnode::mscszAttrWidth);
    
            if ( strWidth.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strWidth.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                szNew.setWidth(static_cast<int>((dblWidth * (strWidth.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the horizontal position percentage based?
            QString strX = strGetAttr(clsXMLnode::mscszAttrX);
    
            if ( strX.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strX.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setX(static_cast<int>((dblWidth * (strX.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Is the vertical position percentage based?
            QString strY = strGetAttr(clsXMLnode::mscszAttrY);
    
            if ( strY.endsWith(clsXMLnode::msccPercent) == true
            && (intPercent = strY.indexOf(clsXMLnode::msccPercent)) > 0 ) {
                ptNew.setY(static_cast<int>((dblHeight * (strY.mid(0, intPercent).toDouble() / 100.0))));
            }
    //Set window geometry
            if ( szCurrent != szNew || ptCurrent != ptNew ) {
                QRect rctGeom(ptNew, szNew);
                mpobjWidget->setGeometry(rctGeom);
            }
        }
    //Get all child nodes
        lstOfNodes lstChildren = lstGetChildNodes();
        foreach( clsXMLnode* pobjChild, lstChildren ) {
    //Does this child have any children?
            pobjChild->resize(pszDeltas);
        }
    }
    

Log in to reply