Qt右键单击QPushButton

12

我正在使用Qt Creator来创建一个扫雷游戏的GUI界面。如何检测右键单击QpushButton事件?这个事件是用哪个信号来触发的呢?


你可能需要重写 event() 并手动发射信号。 - rainer
1
为什么会有人给这个问题点-1?是的,可能还需要更多的努力,但这个问题是一个好问题。感谢穆罕默德提供了一个好答案。 - zeFree
4个回答

21

mousePressEvent槽中创建带有过滤器的自定义按钮。

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

现在就像这样连接
QRightClickButton *button = new QRightClickButton(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));

在MainWindow.cpp中创建一个插槽。
void MainWindow::onRightClicked()
{
    qDebug() << "User right clicked me";
}

对我有效!


2
如果有人想要将connect()连接到通用的clicked()信号和自定义的rightClicked()信号 - 必须在重写的mousePressEvent(QMouseEvent *e)方法的末尾调用QPushButton::mousePressEvent(e); - Krzysiek

6

我认为QPushButton内部实现了仅监听左键单击的功能。但是你可以轻松地扩展QPushButton并重新实现例如鼠标释放事件,如果按下了右键,则可以执行自定义操作,例如发射一个rightClicked()信号:

signals:
    void rightClicked();

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

或者你可以创建一个重载的clicked信号,将鼠标事件指针转发,这样你就可以在按钮外部进行相同的检查。

signals:
    void clicked(QMouseEvent *);

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

然后,在您连接按钮的clicked(QMouseEvent *)信号的插槽中进行检查,并相应地进行处理。


我正在使用 QPushButton,但是它里面没有 button()。我该怎么办? - Khosi
@KhoC 什么?button()QMouseEvent的一个方法。 - cmannett85
所以我不知道如何使用mouseReleaseEvent。为什么你在mouseReleaseEvent中调用rightClicked() - Khosi
@KhoC - 因为clicked事件发生在您按下并释放按钮时。这样,您就可以获得默认行为 - 当您单击按钮但在释放之前将鼠标移出它时 - 您不会获得单击。您可以根据需要自定义它,也可以使用mousePressEvent - dtech
为什么不在这里调用父类的mouseReleaseEvent(),而是手动发出clicked()信号呢? - eepp

3
我刚刚编写了这个小帮助适配器,它可以使任何现有的按钮成为可右键单击的按钮,无需对其进行子类化:

我刚刚编写了这个小帮助适配器,它可以使任何现有的按钮成为可右键单击的按钮,无需对其进行子类化:

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

使用方法:

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

从现在开始,右键点击和左键点击都将触发clicked信号。无需删除此对象-它使用ui->pushButton作为父对象,并且当父对象被销毁时,Qt会自动删除它。
显然,如果需要,你可以写两行代码(字面意义上)在这里声明一个新的信号,并在右键单击而不是clicked时发射该信号。

这段代码很棒,因为我在子类化方面遇到了一些严重的问题(我是qt新手)。只想指出一些重要的事情,如果您右键单击对象太快,它将不稳定。您还需要处理QEvent::MouseButtonDblClick!实际上,我可能还会说它应该改为QEvent::MouseButtonRelease,因为那时候才运行单击,而不是按下。 - Steven Lu
@StevenLu,这是一个好的和明智的建议,谢谢你指出!我很高兴听到我的小代码片段有所帮助。 - Violet Giraffe

0

我也想建议这个选项,而不需要事件过滤器/其他东西...

    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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接