9

I'm working on a Qt application (in C++). Without appyling any styles, my menu looks like this:

enter image description here

I'd like it to look like this:

enter image description here

How do I achieve this? Either using qss, or programmatically?

I already tried this, without success:

    menu->addAction(tr("Add"), this, SLOT(CreateNewWaypoint()))->setIconVisibleInMenu(false);

Answers for both Qt4.8 and Qt5 are needed to get the full bounty!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
JoergEwald
  • 379
  • 3
  • 10
  • Looks relevant: https://stackoverflow.com/questions/208411/in-qt-for-a-context-menu-item-how-to-hide-the-space-of-the-icon – Azeem Jun 25 '17 at 10:56
  • For setting your own `stylesheet` for `QMenu`: https://stackoverflow.com/questions/31399610/qmenu-how-to-customize-the-menu-items-of-qmenu – Azeem Jun 25 '17 at 11:13
  • Thanks, both touch on the subject, yes. My main problem is how to address the individual parts of the menu with style sheets. I couldn't find a comprehensive list for that. – JoergEwald Jul 06 '17 at 09:26
  • @mimo Are you using Qt4 or Qt5? – eyllanesc Jul 20 '18 at 16:23
  • Qt5. I am hesitating in removing the reference to Qt4.8 in the question, but since I am not the author, I am not it is right to do it... – mimo Jul 20 '18 at 16:25
  • @mimo instead of eliminating it, add to the question that the solution you want for Qt5. – eyllanesc Jul 20 '18 at 16:28
  • @mimo try with my answer :) – eyllanesc Jul 20 '18 at 17:30

3 Answers3

7

One way to solve the problem is to use QProxyStyle:

customstyle.h

#ifndef CUSTOMSTYLE_H
#define CUSTOMSTYLE_H
#include <QProxyStyle>
#include <QStyleOptionMenuItem>

class CustomStyle : public QProxyStyle{
public:
    using QProxyStyle::QProxyStyle;

    void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const override
    {
        if(element == QStyle::CE_MenuItem){
            QStyleOptionMenuItem myMenuOption;
            const QStyleOptionMenuItem *menuOption =
                    qstyleoption_cast<const QStyleOptionMenuItem *>(opt);
            if (menuOption) {
                const int width = pixelMetric(PM_SmallIconSize)+6;
                myMenuOption = *menuOption;
                QRect r(myMenuOption.rect);
                r.setLeft(-width);
                myMenuOption.rect = r;
            }
            QProxyStyle::drawControl(element, &myMenuOption, p, w);
            return;
        }
        QProxyStyle::drawControl(element, opt, p, w);
    }
};

#endif // CUSTOMSTYLE_H

then you install it in the QApplication:

QApplication a(argc, argv);
QApplication::setStyle(new CustomStyle);
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
6

You can influence on how your menu appears by playing with its style sheet. With you example code you can do the following:

menu.setStyleSheet("QMenu::item {"
                   "padding: 2px 5px 2px 2px;"
                   "}"
                   "QMenu::item:selected {"
                   "background-color: rgb(0, 85, 127);"
                   "color: rgb(255, 255, 255);"
                   "}");

Note the padding property, which sets the offsets of your menu item rectangles.

vahancho
  • 20,808
  • 3
  • 47
  • 55
0

I wanted to get rid of the icons in the standard context menu for a QPlainTextEdit.

Just using setIconVisibleInMenu(false) for all the actions in the QMenu still left the icon space as shown in the question.

I was only able to get rid of the icon space when I set the icon for the menu actions to a null icon.

Full example:

void CustomPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu *menu = createStandardContextMenu();

    foreach (QAction *action, menu->actions()) {
        action->setIcon(QIcon());
    }

    menu->exec(event->globalPos());
    delete menu;
}
itsmejoeeey
  • 302
  • 3
  • 11