[Solved] Keeping a menubar for repeated use in QMainWindow::setMenuBar
-
@Chris-Kawa
i see. Because it's contained in a layout.
Sry for that. -
@Chris-Kawa
That's a very simple solution to the problem.
Thank you, I'll be trying it out very soon. -
@raven-worx, @chris-kawa
http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qmainwindow.cpp?h=5.5#n517
I'm sorry to argue, but look up here. Line 535 explicitly deletes the menu! -
@kshegunov That's true, but note that deletion happens in
if (topLayout->menuBar() ....
block.
When you set parent of the bar to nullptr it is taken out of the layout. But don't take my word for it, check:qDebug() << mainWindow->layout()->menuBar(); //prints out some pointer mainWindow->menuBar()->setParent(nullptr); qDebug() << mainWindow->layout()->menuBar(); //prints 0, the bar was taken out
-
@Chris-Kawa
Ah! Yes, you're correct of course. This was my initial idea (reparenting the menu bar) but I discarded it because I didn't realize that the menu will be taken out of the layout, silly me! :)Kind regards.
-
Solution verified as simple and perfectly working.
What I did was to override QMainWindow::setMenuBar as follows :
void myMainWindow::setMenuBar(QMenuBar * bar) { if (menuBar()) menuBar()->setParent(0); // detach current menubar so it won't get deleted QMainWindow::setMenuBar(bar); }
-
@Harry123
please be advised that this only works as long as the instance is of the type myMainWindow, since setMenuBar() is not virtual.Meaning the following wont work, even the object behind the pointer has the correct type:
QMainWindow* mw = new myMainWindow; // pointer-type is different from instance-type! mw->setMenuBar(...);
-
I have "mw = this;" in the constructor for myMainWindow, where mw is a global variable, and I can now successfully do "mw->setMenuBar(..)" from several other classes with no problem.
It currently does work - why shouldn't it ?
-
@Harry123 It might work for your case but is very dangerous in general. As @raven-worx mentioned
setMenuBar()
is not virtual. This means that if anyone calls it through a pointer to base class the base class version will be called (which deletes the bar).
In general you can't guarantee that your class will only by accessed via pointer to derived class and in fact you should never assume that.
Example:QMainWindow* gotcha = mw; mw->setMenuBar(someBar); //ok gotcha->setMenuBar(someOtherBar); //someBar is deleted!
Long story short - don't override non-virtual methods. Create a new one with descriptive name.
-
@Chris-Kawa
I don't have this gotcha - my variable is of type myMainWindow*.
This can only not work if there is a bug in the C++ compiler.
But perhaps I will rename it, just in case. -
@Harry123 said:
This can only not work if there is a bug in the C++ compiler.
As I said - it works here and now for you. But who's to say in a month or a year another person will for whatever reason create a local variable of type QMainWindow* and copy your pointer. The point is that because this method is not virtual a different method will be called depending on the type of pointer you access it through. That's a time bomb type of bug. It does not explode here and now for you but it will for someone else or future you.
-
@Chris-Kawa
Totally agree.