How to disable the entire widget except for a specific widget in a multi-layered nested widget?
-
@John-Van said in How to disable the entire widget except for a specific widget in a multi-layered nested widget?:
After setParent (nulliptr), the position of the widget will change, which is not what I expected.
If you don't want/like the solutions and suggestions we provided, the final answer to your question:
How to disable the entire widget except for a specific widget in a multi-layered nested widget ?
is short and simple:
You cannot.
@JonB said in How to disable the entire widget except for a specific widget in a multi-layered nested widget?:
More work but (presumably) doable.
Easy ;-)
QString activeWidget = "button_not2disable"; // objectname for (auto &w : findChildren<QWidget *>(QRegularExpression(QString("^(?!%1)\\w+").arg(activeWidget)), Qt::FindChildrenRecursively) ) w->setDisabled(true);
Edit:
Fixed RegEx
Solution only valid if your widgets are direct children of current class... else it disables one parent, which also disables your target widget...Edit_2:
Fixed recursion :))
Now also works when target is some layers deep in the QObject tree behind other widgets, which have to stay enabled// ########################################################### /// Disable everything recursively, except target widget QString targetWidgetName = "button_42"; // objectname of widget that should be active for (auto &w : findChildren<QWidget *>(QRegularExpression(QString("^(?!%1)\\w+").arg(targetWidgetName)), Qt::FindChildOption::FindChildrenRecursively) ) { qDebug() << w->objectName() << "disabled"; w->setDisabled(true); } // ############################################################ /// enable everything needed by moving upwards the parent-child hierarchy starting from target auto target = findChild<QWidget * >(targetWidgetName); while (target->parentWidget() != nullptr) { target = target->parentWidget(); qDebug() << target->objectName() << "enabled"; target->setDisabled(false); }
-
@John-Van said in How to disable the entire widget except for a specific widget in a multi-layered nested widget?:
If the parent widget is disabled, all child widgets will become disabled.
That's expected and can't be changed.
You need one top level (=parentless) widget, to display a window.
If you disable the top level widget, and display one of its children, callsetParent(nullptr)
, then enable and show it. It will become a top level widget of its own. If you want to restore the previous order, you need to set its old parent and also embed into its previous layout if it was part of one. -
What @Axel-Spoerl described above sounds a little like my solution for this topic here. In addition you can disable the parent, while the child is shown as standalone widget.
Another solution:
Don't disable the whole parent widget. Disable only parts of it.
You can disable aQGroupBox
for example, which then does not disable other widgets in the same window that are not part of your groupbox. -
@Axel-Spoerl After setParent (nulliptr), the position of the widget will change, which is not what I expected.
-
@John-Van
Then what did you expect? If a widget has a parent it is positioned with respect to its parent. If it has no parent it is not positioned with respect to the parent it used to have but no longer has, it is now a "top level" widget. If you want it positioned relative to some other widget (e.g. its old parent) you would have to move it appropriately yourself.You can't disable the parent of a non-disabled child/descendant, since disabling a parent by definition disables its descendants. As @Pl45m4 says, it sounds like what you might really mean is to disable all other children of a parent keeping only one child enabled. More work but (presumably) doable.
-
@John-Van said in How to disable the entire widget except for a specific widget in a multi-layered nested widget?:
After setParent (nulliptr), the position of the widget will change, which is not what I expected.
If you don't want/like the solutions and suggestions we provided, the final answer to your question:
How to disable the entire widget except for a specific widget in a multi-layered nested widget ?
is short and simple:
You cannot.
@JonB said in How to disable the entire widget except for a specific widget in a multi-layered nested widget?:
More work but (presumably) doable.
Easy ;-)
QString activeWidget = "button_not2disable"; // objectname for (auto &w : findChildren<QWidget *>(QRegularExpression(QString("^(?!%1)\\w+").arg(activeWidget)), Qt::FindChildrenRecursively) ) w->setDisabled(true);
Edit:
Fixed RegEx
Solution only valid if your widgets are direct children of current class... else it disables one parent, which also disables your target widget...Edit_2:
Fixed recursion :))
Now also works when target is some layers deep in the QObject tree behind other widgets, which have to stay enabled// ########################################################### /// Disable everything recursively, except target widget QString targetWidgetName = "button_42"; // objectname of widget that should be active for (auto &w : findChildren<QWidget *>(QRegularExpression(QString("^(?!%1)\\w+").arg(targetWidgetName)), Qt::FindChildOption::FindChildrenRecursively) ) { qDebug() << w->objectName() << "disabled"; w->setDisabled(true); } // ############################################################ /// enable everything needed by moving upwards the parent-child hierarchy starting from target auto target = findChild<QWidget * >(targetWidgetName); while (target->parentWidget() != nullptr) { target = target->parentWidget(); qDebug() << target->objectName() << "enabled"; target->setDisabled(false); }
-