Search code examples
qtqtstylesheetsqmenu

QMenu Right Align Text


I need the text in my QMenu to be right aligned instead of left aligned.

QMenu menu;
menu.setStyleSheet("QMenu{background: #2e353d; color: #bfbfbf; margin: 0px;}"
"QMenu::item{font-size: 10pt; padding: " + QString::number(6*globalDPI) + "px " + QString::number(30*globalDPI) + "px " + QString::number(6*globalDPI) + "px " + QString::number(20*globalDPI) + "px; border: 0px solid transparent; margin: 0px;}"
"QMenu::item:selected{background: #373f49; color: #fff;}");

menu.addAction("Debug Log");
menu.addAction("Website");
menu.addAction("Changelog");
menu.addAction("About");

menu.exec(myButton->mapToGlobal(QPoint(0,32*globalDPI)));

I've tried adding text-align: right to both the QMenu and QMenu::item in the stylesheet. I've tried setting the layout direction to right to left with setLayoutDirection. I've tried adding subcontrol-position: right; to the stylesheet. Nothing works, the text in the menu remains left aligned.

Any ideas?


Solution

  • You will not be able to change the alignment of the QMenu text as it is codified when drawing the QMenu using the QStyle. A workaround is to use a QProxyStyle by doing the painting by passing an empty text in the QStyleOptionMenuItem and then painting the text (the text painting I show is limited since I am not taking all cases such as a QMenu with multiple lines and other options sophisticated).

    #include <QtWidgets>
    class MenuProxyStyle: 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){
                if(const QStyleOptionMenuItem *o = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)){
                    QStyleOptionMenuItem menuitem = *o;
                    QString text = o->text;
                    menuitem.text = "";
                    QProxyStyle::drawControl(element, &menuitem, p, w);
                    if(o->text.isEmpty())
                        return;
                    int margin = 4;
                    int text_flags = Qt::AlignVCenter | Qt::AlignRight | Qt::TextDontClip | Qt::TextSingleLine;
                    p->drawText(menuitem.rect.adjusted(margin, margin, -margin, -margin),  text_flags, text);
                    return;
                }
            }
            QProxyStyle::drawControl(element, opt, p, w);
        }
    };
    class Widget: public QWidget{
    public:
        Widget(QWidget *parent=nullptr): QWidget(parent){
            setContextMenuPolicy(Qt::CustomContextMenu);
            connect(this, &QWidget::customContextMenuRequested, this, &Widget::on_customContextMenuRequested);
        }
    private:
        void on_customContextMenuRequested(const QPoint &pos){
            QMenu menu;
            menu.setStyle(new MenuProxyStyle(menu.style()));
            menu.addAction("Debug Log");
            menu.addAction("Website");
            menu.addAction("Changelog");
            menu.addAction("About");
            menu.exec(mapToGlobal(pos));
        }
    };
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        Widget w;
        w.resize(640, 480);
        w.show();
        return app.exec();
    }