[SOLVED] Qt – Edit button text on right click

Issue

I want to create a button that when the user right clicks on the button, a context menu comes up giving the user the option to replace the text on the button. When the user chooses the replace option, they can edit the text label on the button itself.

I’ve got the right click to create the context menu, and I can intercept the key events to change the label, but when I do this, I’ve got to deal with all the various keyboard functions, like deleting, for myself.

I’m wondering if there is a better way to do this. Is there a way that I can put a QLineEdit on a button to edit the button text?

This is the code that I’ve started.

EventButton::EventButton(QWidget *parent) : 
    QPushButton(parent) 
{ }

void EventButton::mousePressEvent(QMouseEvent *e) {
    if (e->button() == Qt::RightButton) {
        QMenu contextMenu;
        contextMenu.addAction("Replace Text", this, [=] {
            this->grabKeyboard();
            this->setText("");
        });

        QPoint globalPos = mapToGlobal(e->pos());
        contextMenu.exec(globalPos);
    } else {
        emit clicked();
    }
}

void EventButton::keyPressEvent(QKeyEvent *e) {
    // Check for return key
    if ((e->key() == Qt::Key_Enter) || (e->key() == Qt::Key_Return)) {
         this->releaseKeyboard();
         emit buttonTitleChanged(this->text());
    } else {
         QString text = this->text();
         text.append(e->key());
         this->setText(text);
    }
}

Solution

You can just add a QLineEdit child to the button. I would also give the button a grid layout to automatically handle the line edit positioning and resizing and override contextMenuEvent to show the menu, to end up with something like this:

#include <QPushButton>
#include <QMenu>
#include <QAction>
#include <QContextMenuEvent>
#include <QGridLayout>
class EventButton : public QPushButton
{
    Q_OBJECT
    QLineEdit * lineEdit;
public:
    explicit EventButton(const QString &text, QWidget *parent) :
        QPushButton(text, parent)
    {
        lineEdit = new QLineEdit();
        lineEdit->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
        lineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
        connect(lineEdit, &QLineEdit::editingFinished, [=](){
                    setText(lineEdit->text());
                    lineEdit->hide();
                });

        QGridLayout * gridlayout = new QGridLayout();
        gridlayout->setMargin(0);
        setLayout(gridlayout);
        gridlayout->addWidget(lineEdit);
        lineEdit->hide();
    }
protected:
    void contextMenuEvent(QContextMenuEvent *event) override
    {
        QMenu contextMenu;
        contextMenu.addAction("Replace Text", this, [=] {
            QString text = this->text();
            lineEdit->setText(text);
            lineEdit->setSelection(0, text.size());
            lineEdit->show();
            lineEdit->setFocus();
        });

        QPoint globalPos = mapToGlobal(event->pos());
        contextMenu.exec(globalPos);
    }
};

Answered By – p-a-o-l-o

Answer Checked By – Robin (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *