Important: Please read the Qt Code of Conduct -

How to render shortcut text in custom button?

  • Hi Friends,
    I am creating a custom Button that receives an Action, something like this:

            CustomButton {
                action: Action {
                    icon.width: 24
                    icon.height: 24
                    icon.source: "/icons/save.svg"
                    text: qsTr("&Save")
                    onTriggered: {

    In the custom button I have a Text Item with the action's text:

            Text {
                height: root.action.icon.height
                text: root.action.text
                verticalAlignment: Text.AlignVCenter
                color: area.containsMouse ? palette.brightText : palette.highlightedText

    The problem is that the text is rendered as it is "&Save" and I need it to be rendered as "Save" with "S" underlined. As it is with builtin menus and buttons.

    Does anyone knows how to do that?


  • You can use MenuItem:

    MenuItem {
            width: 100
            height: 30
            text: "&Start"

    Docs say its a convenience item based upon AbstractButton.

  • The whole point is not to use MenuItem, The idea is to create a custom Item.

  • @mnesarco Could you add a bit of code in your custom button - specifically in the Text item - to parse the action text into a rich text string? So "&Save" would be transformed to "<b>S</b>ave".

            Text {
                height: root.action.icon.height
                text: transformText(root.action.text)
                def transformText(t) { ... }

  • @mnesarco - I copied your code and ran it but changed CustomButton to Button and it works, the 'S' is underlined


  • @Markkyboy this is funny, the Idea is to create a custom component not to use the builtin Button component that obviously works.

  • @Bob64 That is what I do right now as a workaround. But I wonder if there is a way to do it calling some builtin functionality.

  • I have found this class in Qt sources: QQuickMnemonicLabel it has a function that translate the mnemonic text into the undelined version. But this class is private.

    This is the whole class source:

    #include "qquickmnemoniclabel_p.h"
    #include <QtQuick/private/qquicktext_p_p.h>
    QQuickMnemonicLabel::QQuickMnemonicLabel(QQuickItem *parent)
        : QQuickText(parent)
    QString QQuickMnemonicLabel::text() const
        return m_fullText;
    void QQuickMnemonicLabel::setText(const QString &text)
        if (m_fullText == text)
        m_fullText = text;
    bool QQuickMnemonicLabel::isMnemonicVisible() const
        return m_mnemonicVisible;
    void QQuickMnemonicLabel::setMnemonicVisible(bool visible)
        if (m_mnemonicVisible == visible)
        m_mnemonicVisible = visible;
        if (isComponentComplete())
    static QTextLayout::FormatRange underlineRange(int start, int length = 1)
        QTextLayout::FormatRange range;
        range.start = start;
        range.length = length;
        return range;
    // based on QPlatformTheme::removeMnemonics()
    void QQuickMnemonicLabel::updateMnemonic()
        QString text(m_fullText.size(), QChar::Null);
        int idx = 0;
        int pos = 0;
        int len = m_fullText.length();
        QList<QTextLayout::FormatRange> formats;
        while (len) {
            if ( == QLatin1Char('&') && (len == 1 || + 1) != QLatin1Char('&'))) {
                if (m_mnemonicVisible && (pos == 0 || - 1) != QLatin1Char('&')))
                    formats += underlineRange(pos);
                if (len == 0)
            } else if ( == QLatin1Char('(') && len >= 4 &&
              + 1) == QLatin1Char('&') &&
              + 2) != QLatin1Char('&') &&
              + 3) == QLatin1Char(')')) {
                // a mnemonic with format "\s*(&X)"
                if (m_mnemonicVisible) {
                    formats += underlineRange(pos + 1);
                } else {
                    int n = 0;
                    while (idx > n && - n - 1).isSpace())
                    idx -= n;
                    pos += 4;
                    len -= 4;
            text[idx] =;

    So, I am afraid that the javascript function solution is the only way to go, ugly but works. There is also a StackOverflow post about this:

  • @mnesarco said in How to render shortcut text in custom button?:

    This is the whole class source:

    That does replace the text, but I don't see it generating a keyboard action. I would have thought the default buttons actually generate a keyboard action shortcut.

  • Apparently there is no builtin solution for this. It must be done in application code. Do I have to mark this topic as Solved?

Log in to reply