Customizing Menu
-
Hi, I am trying to customize a Menu and I am getting a weird behaviour that I do not understand... Using a plain
Menu { id: root function getMenuWidth() { var result = 0; var padding = 15; for (var i = 0; i < count; ++i) { var item = itemAt(i); if (!(item instanceof MenuSeparator)) { result = Math.max(item.contentItem.implicitWidth, result); padding = Math.max(item.padding, padding); } } return Math.max(125, result + padding * 2 + 10); } Component.onCompleted: { root.width = getMenuWidth(); } }
yields me this result:
When trying to assign the menu-popup a different background color or radius, I thought, I could do it like that:
Menu { id: root background: Rectangle { id: testRect color: "black" radius: 10 } ... }
However, I get this result:
I don't understand, where those massive margins come from or how do make them smaller. Decreasing the Menu width, just decreases the width of the content, but the margins remain huge. Anyone have an idea how to solve this?
-
not sure this is the real cause of your problem but why do you make it in Component.onCompleted instead of binding the width property to your function ? You assign a width only on component completion. But what guarantees you that the width doesn't change AFTER completion ? My bet is that the width changes after. If the menu is resized after completion, then it's normal that it doesn't work as you intended.
Menu { width: getMenuWidth() }
should ensure that the width is recomputed as soon as one property inside the function has changed.
EDIT : sorry I think I misunderstood the problem, but I still think that the function should be directly bound to the property, instead of assigning it at component completion. I had watched source code of some Control items a few monthes ago, including menu, and as far as I remember, the menu gives a default size to the background item, and you didn't override them.
-
not sure this is the real cause of your problem but why do you make it in Component.onCompleted instead of binding the width property to your function ? You assign a width only on component completion. But what guarantees you that the width doesn't change AFTER completion ? My bet is that the width changes after. If the menu is resized after completion, then it's normal that it doesn't work as you intended.
Menu { width: getMenuWidth() }
should ensure that the width is recomputed as soon as one property inside the function has changed.
EDIT : sorry I think I misunderstood the problem, but I still think that the function should be directly bound to the property, instead of assigning it at component completion. I had watched source code of some Control items a few monthes ago, including menu, and as far as I remember, the menu gives a default size to the background item, and you didn't override them.
@ankou29666 as far as I know that is not how QML works. I have always assumed that if a function is used in a property binding then any dependency on other properties must be visible in the argument list. Otherwise the function will execute once and that will be it.
So you would have to do something like:
width: getMenuWidth(property1, property2, ...)
where the
property<N>
are the properties that are used to compute the width. If one of them changes, the RHS will be re-evaluated andwidth
itself will be updated. -
thanks for feedback Bob, but so far i've always passed functions without arguments (empty parentheses) and have never had any problem with property changing without being declared as a function parameter.
-
thanks for feedback Bob, but so far i've always passed functions without arguments (empty parentheses) and have never had any problem with property changing without being declared as a function parameter.
@ankou29666 Thank you - that's interesting. I might have been making an invalid assumption for a long time in that case!
Edit: I haven't had chance to try it but this post confirms what you say:
https://forum.qt.io/post/518444
I can't believe I have gone so long believing this.