DooshBlonk
DooshBlonk

Reputation: 27

Is there a way to access QMainWindowPrivate or QMainWindowLayout?

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

Answers (1)

Scheff's Cat
Scheff's Cat

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

Output: Snapshot of testQMainWindow-takeCentralWidget

Upvotes: 1

Related Questions