Reputation: 27
I'm using Qt5 and I am trying to do this:
setCentralWidget(wid);
...
setCentralWidget(nullptr); // i don't want it to do deleteLater() for my wid variable
...
setCentralWidget(wid);
The problem is that, when I call setCentralWidget(nullptr)
, it does deleteLater()
for my wid
variable.
So, I found a way to use setCentralWidget()
without deleting the wid
variable:
Q_D(QMainWindow);
d->layout->setCentralWidget(nullptr);
But the question is: How to use private headers or widgets or whatever? I mean, I don't have access to QMainWindowPrivate
or QMainWindowLayout
, because they are private. So is there a way to access them?
Upvotes: 1
Views: 109
Reputation: 20171
OP's issue is caused by using setCentralWidget(nullptr);
.
QMainWindow::setCentralWiget():
Sets the given widget to be the main window's central widget.
Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.
(Emphasis mine.)
Hence, for
setCentralWidget(wid);
...
setCentralWidget(nullptr);
it has to be expected that the QMainWindow
will delete the wid
. Otherwise, the wid
instance could become orphaned i.e. a memory leak.
However, OPs issue can be solved without adventurous accesses to internals of QMainWindow
(which is neither intended nor necessary).
In fact, there is an alternative to remove the central widget and take over the ownership again – QMainWindow::takeCentralWidget():
Removes the central widget from this main window.
The ownership of the removed widget is passed to the caller.
(Emphasis mine, again.)
An MCVE to demonstrate this:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QMainWindow qWinMain;
qWinMain.setWindowTitle("QMainWindow::takeCentralWidget");
QLabel *pQLbl = new QLabel("The\ncentral\nwidget");
pQLbl->setAlignment(Qt::AlignCenter);
qWinMain.setCentralWidget(pQLbl);
qWinMain.show();
QTimer qTimer;
qTimer.setInterval(1000);
uint n = 10;
// install signal handlers
QObject::connect(&qTimer, &QTimer::timeout,
[&]() {
--n;
if (!n) {
qWinMain.setCentralWidget(nullptr);
app.quit();
} else if (n & 1) qWinMain.setCentralWidget(pQLbl);
else qWinMain.takeCentralWidget();
});
// runtime loop
qTimer.start();
return app.exec();
}
Upvotes: 1