Solved 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); } }