سؤال

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?

هل كانت مفيدة؟

المحلول

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();
}

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!

نصائح أخرى

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.

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.

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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top