c++qtqmenu

How to resize a QLabel displayed by a QWidgetAction after changing it's text


I use a QWidgetAction to add a header to a context menu (that will also show up on Windows, no matter what style is used, in contrast to addSection(), which does not always actually display the title).

The action's widget is a QLabel. It's text is changed by each invocation of the context menu. The menu is setup in the constructor of my class, and the QWidgetAction is added like so (all m_ variables are member variables declared in the header):

m_contextMenu = new QMenu(this);
m_menuTitle = new QLabel;
m_menuTitle->setAlignment(Qt::AlignCenter);
m_menuTitle->setMargin(4);
QWidgetAction *titleAction = new QWidgetAction(m_contextMenu);
titleAction->setDefaultWidget(m_menuTitle);
m_contextMenu->addAction(titleAction);
m_contextMenu->addSeparator();

When the menu is requested, the text of the label is changed and the menu is displayed like so:

m_menuTitle->setText(tr("%1 „%2“").arg(some_variable, some_other_variable));
...
m_contextMenu->exec(place_to_display);

When the label's text is set for the first time (with a short text the label's text is set to), everything is fine:

enter image description here

but when it's set to some longer text, the size remains the same and the text is cropped:

enter image description here

I tried to fix this, but the only working solution I found was to define the QActions displayed in the menu in the constructor, owned by this, setting the label's text, clearing the menu and adding the actions again, like so:

m_contextMenu->clear();

m_menuTitle->setText(tr("%1 „%2“").arg(some_variable, some_other_variable));

m_contextMenu->addAction(m_menuTitleAction);
m_contextMenu->addSeparator();
m_contextMenu->addAction(m_editAction);
m_contextMenu->addAction(m_deleteAction);

m_contextMenu->exec(place_to_display);

Is there a way to resize the title without rebuilding the menu each time?


Solution

  • The solution is to send a resize event instead:

    m_menuTitle->setText(tr("%1 „%2“").arg(some_variable, some_other_variable));
    ...
    QResizeEvent re(new_size, m_contextMenu->size());
    qApp->sendEvent(m_contextMenu, &re);
    

    This will set the QMenu's internal itemsDirty flag and will force geometry recalculation when the menu is shown. Note that the new size in the event does not matter, as the menu will aways resize based on its sizeHint()!