Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

menuP->setParent() vs. creating by sending parent to constructor



  • On Windows, if i do this:

    QMenu	*menuP(new QMenu(NULL));
    		
    menuP->setParent(parentP);
    

    the sub menu draws OVER it's parent's menu, when i click on the parent menu, like this:

    0_1552253854403_Screen Shot 2019-03-10 at 2.33.12 PM.png

    but if I create it like this:

    QMenu	*menuP(new QMenu(parentP));
    

    it works:

    0_1552255276091_Screen Shot 2019-03-10 at 3.00.54 PM.png

    on mac it works either way. what's the difference on windows and why? i prefer the first way due to the way my code is set up, it's a hack to do it the 2nd way. thanks.



  • calling menu->setAttribute(Qt::WA_NativeWindow); after menu creation didn't help. the only thing that worked was passing the parent menu in at creation time.


  • Lifetime Qt Champion

    Hi,

    macOS menu bar has nothing to do with Windows menu bar. Qt does some automatic re-organisation to fit your menu bar within macOS guidelines.

    If I may, QMenuBar already provides methods to create menues, why not use them ?



  • Hi @SGaist thanks for helping! :)

    macOS menu bar has nothing to do with Windows menu bar
    

    yes but an abstracted API is supposed to insulate me from those differences, right?

    why not use [a completely different way of doing things]
    

    well, to be honest it's because this is legacy code, and the architecture demands it (without re-architecting the entire menu system that already exists in this monolithic, 15 year old code base)

    so back to the question: why doesn't this work, what is missing?

    shouldn't setParent() do the same thing on both platforms?


  • Moderators

    @davecotter said in menuP->setParent() vs. creating by sending parent to constructor:

    so back to the question: why doesn't this work, what is missing?

    shouldn't setParent() do the same thing on both platforms?

    I don't know the answer, but it could be a bug/regression (especially if it worked 15 years ago).

    I suggest you subscribe to the Interest mailing list and ask there. Qt engineers might be able to give you better insight.


  • Moderators

    @davecotter said in menuP->setParent() vs. creating by sending parent to constructor:

    yes but an abstracted API is supposed to insulate me from those differences, right?

    Correct, but this is not always easy or even possible.

    so back to the question: why doesn't this work, what is missing?
    shouldn't setParent() do the same thing on both platforms?

    Yes, in principle ... and here comes the "but" ...
    QMenu is a widget and as such it's subject to it being either a native widget, or an alien widget. Between some versions of Qt4 (can't remember the exact ones) all widgets that don't have a parent widget on creation (* read further for the choice of word "creation") are initialized as native ones, while the ones that have a parent are aliens. And the differences are (unfortunately) significant. If the widget's native, as you might've guessed, a handle for a window is created through the window manager and initialized after that, whereas alien widgets don't posses their own handle and draw onto the their ancestor's surface. This is what I think you observe.

    You can set Qt::WA_NativeWindow as a window attribute to your menu and if I'm right it should fix your issue, but this might come with a runtime cost (native handles can be expensive on some platforms, hence the aforementioned change).

    * Here "creation" refers to the actual initialization of the paint surface as opposed to the object construction, or more specifically - the call to QWidget::create. The timing between object construction and handle initialization may differ in some (edge) cases.



  • widgets that don't have a parent widget on creation are initialized as native ones

    isn't that what we WANT? Native menus?

    You can set Qt::WA_NativeWindow as a window attribute to your

    How do you do that when creating a QMenu? the only option is to pass a parent widget or not?

    meanwhile, i have more or less codified the "hack" method of creating my menus (by passing their parents upon creation rather than setting them later). it's not pretty in my code, but it works perfectly.

    unrelated: how did you hilight the API stuff in RED? what markup is that? there's no button for it in the message composer


  • Moderators

    @davecotter said in menuP->setParent() vs. creating by sending parent to constructor:

    isn't that what we WANT? Native menus?

    Probably. Native menus are different from native windows however (at least on some platforms). Let me give you an example where the menu is a different "object" from the window. The window goes by HWND (an opaque pointer to some internal window structure), while the menu is HMENU. In the general case these two are different types (and presumably implemented differently) so the menu and the window are not interchangeable. I was talking about the drawing surfaces (i.e. the windows), not about the menus, as I haven't enough experience with the menus' internals to be sure. Still, if your menu is integrated into the OS, but is drawn for some reason by Qt, then it may be that the offset is wrong because the submenu doesn't have its own window handle. I'm just speculating though, so best is to test it directly if you don't feel like reading the Qt source.

    How do you do that when creating a QMenu? the only option is to pass a parent widget or not?

    You set the attribute to the widget with QWidget::setAttribute. Something like this:

    QMenu * menu = new QMenu;
    menu->setAttribute(Qt::WA_NativeWindow);
    // ...
    

    unrelated: how did you hilight the API stuff in RED? what markup is that?

    Same markup, it's inline code. Put one backtick before the text and one after to get it in red. Like: `Something in red`

    there's no button for it in the message composer

    Oh, I don't know. I write it directly in the text box, I haven't checked what buttons there are in the composer.



  • calling menu->setAttribute(Qt::WA_NativeWindow); after menu creation didn't help. the only thing that worked was passing the parent menu in at creation time.


Log in to reply