Issue
Basically I am using Qt Menu by adding actions with Shortcuts. They look fine when the menu shows up.
But I want to add more spacing between the action item text and its shortcut. Is this possible? I couldn't find any function to do this.
setMinimumWidth works but I need add on top of the dynamic width computed by Qt.
Solution
Due to the complex way QMenu computes its size, using setMinimumWidth()
is not a reliable option: once that size is set, there's no way to unset it, and the sizeHint()
will always use that minimum.
There are two possible workarounds for that, though.
Force layouting of the menu
This is a bit hacky and dirty, and might not work well in all situations. The trick is to force layouting again by adding a "fake" action that will be instantly removed.
You can do this by connecting specific functions to the aboutToShow
and aboutToHide
signals:
def resizeMenu(menu):
for action in menu.actions():
if action.shortcut():
menu.setMinimumWidth(menu.sizeHint().width() + 50)
menu.removeAction(menu.addAction(''))
break
def restoreMenu(menu):
menu.setMinimumWidth(0)
menu.removeAction(menu.addAction(''))
menu.aboutToShow.connect(lambda: resizeMenu(menu))
menu.aboutToHide.connect(lambda: restoreMenu(menu))
You could also install an event filter on the application so that it will work for all menus:
class MenuWatcher(QtCore.QObject):
def eventFilter(self, obj, event):
if isinstance(obj, QtWidgets.QMenu):
if event.type() == event.Show:
for action in obj.actions():
if action.shortcut():
menu.setMinimumWidth(menu.sizeHint().width() + 50)
menu.removeAction(menu.addAction(''))
break
elif event.type() == event.Hide:
if menu.minimumWidth():
menu.setMinimumWidth(0)
menu.removeAction(menu.addAction(''))
return super().eventFilter(obj, event)
# ...
watcher = MenuWatcher()
app.installEventFilter(watcher)
Using a QProxyStyle
By overriding the sizeFromContents()
of a QProxyStyle we can check whether the option is a CT_MenuItem
, and if it has a tabWidth
(indicating that at least a previous action has a shortcut) or a \t
in its text
(meaning that it probably has a shortcut), we can add a specific width before returning the size provided by the default implementation:
class ProxyStyle(QtWidgets.QProxyStyle):
def sizeFromContents(self, ct, opt, size, widget=None):
size = super().sizeFromContents(ct, opt, size, widget)
if ct == self.CT_MenuItem and (opt.tabWidth or '\t' in opt.text):
size.setWidth(size.width() + 50)
return size
# ...
app.setStyle(ProxyStyle())
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.