Qt rightclick QPushButton
Asked Answered
F

4

12

I'm using Qt Creator to create a gui for a mineseeper game. How can I know a QpushButton clicked with rightclick? for flag in the game. In other word, which signal used for rightclick?

First answered 27/3, 2013 at 12:11 Comment(2)
You'll probably need to override event() and emit the signal yourself.Stipel
Why'd any one -1 this question?? Yes, there could have been more efforts, but the question is a good one. Thanks to Muhammad for a good answer.Liebermann
A
21

Create your own button with filter at mousePressEvent slot.

qrightclickbutton.h

#ifndef QRIGHTCLICKBUTTON_H
#define QRIGHTCLICKBUTTON_H

#include <QPushButton>
#include <QMouseEvent>

class QRightClickButton : public QPushButton
{
    Q_OBJECT

public:
    explicit QRightClickButton(QWidget *parent = 0);

private slots:
    void mousePressEvent(QMouseEvent *e);

signals:
    void rightClicked();

public slots:

};

#endif // QRIGHTCLICKBUTTON_H

qrightclickbutton.cpp

#include "qrightclickbutton.h"

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

void QRightClickButton::mousePressEvent(QMouseEvent *e)
{
    if(e->button()==Qt::RightButton)
        emit rightClicked();
    mousePressEvent(QMouseEvent *e)
}

Now connect like this

QRightClickButton *button = new QRightClickButton(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));

Create a slot in MainWindow.cpp.

void MainWindow::onRightClicked()
{
    qDebug() << "User right clicked me";
}

It works for me!

Arcturus answered 27/3, 2013 at 12:31 Comment(1)
If anyone would like to connect() both to the generic clicked() signal and custom rightClicked() signal - it is necessary to call QPushButton::mousePressEvent(e); in the end of overridden mousePressEvent(QMouseEvent *e)Arwood
V
6

I think QPushButton is internally implemented to listen to left mouse clicks only. But you can easily extend QPushButton and re-implement let's say the mouse release event and do your thing if the right mouse button was pressed, e.g. emit a custom rightClicked() signal for example:

signals:
    void rightClicked();

protected:
    void mouseReleaseEvent(QMouseEvent *e) {
        if (e->button() == Qt::RightButton) emit rightClicked();
        else if (e->button() == Qt::LeftButton) emit clicked();
    }

... or you can create an overload of the clicked signal that forwards the mouseEvent pointer so you can do the same check outside of the button.

signals:
    void clicked(QMouseEvent *);

protected:
    void mouseReleaseEvent(QMouseEvent *e) {
        emit clicked(e);
    }

Then you do the check in the slot you connect the button's clicked(QMouseEvent *) signal to and proceed accordingly.

Varletry answered 27/3, 2013 at 12:23 Comment(5)
I'm using QPushButton and there is no button() in that. what should I do?First
@KhoC What?? button() is a method of QMouseEvent.Inerrable
so I don't know how can I use mouseReleaseEvent. why you call rightClicked() in mouseReleaseEvent ?First
@KhoC - because the clicked event occurs when you press and then release the button. This way you get the default behavior - when you click a button but move the mouse out of it before you release - you don't get a click. You can customize that according to your needs, you can also use the mousePressEvent if you like.Varletry
Why not calling the parent's mouseReleaseEvent() instead of emitting clicked() manually here?Cleodell
H
3

I just wrote this little helper adapter to make any existing button right-clickable with no need to subclass it:

class CRightClickEnabler : public QObject
{
public:
    CRightClickEnabler(QAbstractButton * button): QObject(button), _button(button) {
        button->installEventFilter(this);
    };

protected:
    inline bool eventFilter(QObject *watched, QEvent *event) override {
        if (event->type() == QEvent::MouseButtonPress)
        {
            auto mouseEvent = (QMouseEvent*)event;
            if (mouseEvent->button() == Qt::RightButton)
                _button->click();
        }
        return false;
    }

private:
    QAbstractButton* _button;
};

Usage:

connect(ui->pushButton, &QPushButton::clicked, [](){qDebug() << "Button clicked";});
new CRightClickEnabler(ui->pushButton);

From now on, the clicked signal will be triggered by the right click as well as left click. There's no need to delete this object - it uses ui->pushButton as parent and will be auto-deleted by Qt when the parent is destroyed.

Obviously, you can write 2 lines of code (literally) to declare a new signal here and emit that signal upon right click instead of clicked, if desired.

Hail answered 17/10, 2016 at 10:11 Comment(2)
This code is great, because i had some serious issues getting subclassing to work (qt noob here though). Just want to point out something important, this will be flaky if you right click the object too fast. You just have to also handle it for QEvent::MouseButtonDblClick! Actually I'd probably also say it should just be changed to QEvent::MouseButtonRelease since thats when click runs anyway. not on press.Wickner
@StevenLu, that's a good and sensible suggestion, thanks for pointing it out! And I'm glad to hear my little code snippet helped.Hail
P
0

I'd like to suggest this option as well, without need for event filter/other stuffs...

    self.button.released.connect(self.doStuff)
    self.button.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
    self.button.customContextMenuRequested.connect(partial(self.doStuff, False))

    def doStuff(self,state=True,p=QPoint()):
        print("True for left, False for right!",state)
Papyrology answered 28/11, 2021 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.