What are consequences of forcing QObject as a parent of QWidget?
Irrevocable undefined behavior.
Qt is not designed to support a non-widget parent to a QWidget
. I consider it an API bug in Qt, since a QWidget
isn't fully a QObject
in the Liskov Substitution Principle sense because of that limitation.
Qt 4.x will crash when attempting to activate the widget. So it'll work until you focus your application and then will crash.
Qt 5.x asserts in QObject::setParent()
.
The assertion can be bypassed, though:
// https://github.com/KubaO/stackoverflown/tree/master/questions/widget-parent-28992276
#include <QApplication>
#include <QLabel>
class ParentHacker : private QWidget {
public:
static void setParent(QWidget * child_, QObject * parent) {
// The following line invokes undefined behavior
auto child = static_cast<ParentHacker*>(child_);
Q_ASSERT(child->d_ptr->isWidget);
child->d_ptr->isWidget = 0;
child->QObject::setParent(parent);
child->d_ptr->isWidget = 1;
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QLabel w{"Hello!"};
w.setMinimumSize(200, 100);
w.show();
ParentHacker::setParent(&w, &app);
return app.exec();
}
It will crash somewhere else then.
You'd be fighting an uphill battle trying to patch Qt to get it to work. It's not a worthwhile fight, I think - not unless a decision is made to make a QWidget
truly-a QObject
and change its constructor signature. That can be done at the earliest in the next major version of Qt since it's a binary-incompatible change AFAIK.
Moreover, what you're trying to do is mostly unnecessary. You can certainly have a hidden QWidget
parent to multiple stand-alone top-level widgets.
#include <QApplication>
#include <QLabel>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QWidget parent;
QLabel l1{"Close me to quit!"}, l2{"Hello!"};
for (auto label : {&l1, &l2}) {
label->setMinimumSize(200, 100);
label->setParent(&parent);
label->setWindowFlags(Qt::Window);
label->setText(QString("%1 Parent: %2.").
arg(label->text()).arg((quintptr)label->parent(), 0, 16));
label->show();
}
l2.setAttribute(Qt::WA_QuitOnClose, false);
return app.exec();
}
The overhead of having the widget hidden is minimal, you're not wasting any resources by using a QWidget
instead of a QObject
for the parent.
QWidget::setParent(QWidget*)
hidesQObject::setParent(QObject*)
. – Hedgcockstatic_cast
would be more appropriate. Orw->QObject::setParent(o);
. – Hedgcock