0

I want to achieve all the functionality of left button of mouse ( such as clicked(), pressed() , released() , setAutoRepeat() ) on QPushButton from the right button of mouse keeping all the left button functionality intact. Here is the code for re implementation of the eventFilter , which is not giving desirable result.

bool PreciseControl::eventFilter(QObject *, QEvent *event) 
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);


if(event->type() == QEvent::MouseButtonPress &&
                    mouseEvent->button()==Qt::RightButton )
 {


        emit rightMousePressed();
        return true;
 }
else if(event->type() == QEvent::MouseButtonRelease &&
        mouseEvent->button()==Qt::RightButton )
{
        emit rightMouseReleased();
        return true;
}


if(event->type() == QEvent::MouseButtonPress &&
                    mouseEvent->button()==Qt::LeftButton )
 {


        emit leftMousePressed();
        return true;
 }
else if(event->type() == QEvent::MouseButtonRelease &&
        mouseEvent->button()==Qt::LeftButton )
{
        emit leftMouseReleased();
        return true;
}

 return false;}

Can any one help? Thanks in advance.

rugi
  • 115
  • 5
  • 1
    Look into http://stackoverflow.com/questions/15658464/qt-rightclick-qpushbutton. – 9T9 Aug 30 '16 at 06:52
  • As per you example check [link](http://doc.qt.io/qt-4.8/qobject.html#eventFilter) for event fileter, here it is specified that we need to install event filter on object. In your case pushbutton object name. Other way, you can create drive class from QPushbutton and write your own MouseEvent of QPushbotton – Atul N Aug 30 '16 at 07:01
  • Please show an [mcve] and explain exactly what is not working, "is not giving desirable result" is not specific enough. – Mailerdaimon Aug 30 '16 at 07:15
  • @Mailerdaimon I think I have provided Minimal, Complete, and Verifiable example code. As far as "is not giving desirable result" is concerned , let me be more specific. On right button press() , i am not getting auto repeat feature and on left button press leftMousePressed() signal is not emitting. Hope this clears the thing a little bit. – rugi Aug 31 '16 at 04:51
  • @rugi it is great that you got answers that helped you to some extent. This shows that the question is not unusable. But I stand to the point that your code and description is neither complete nor verifiable. Read the artical again, it will help you to get even more and better answers next time you ask a question. – Mailerdaimon Aug 31 '16 at 06:16

2 Answers2

2

You shouldn't use event filters for this. Subclass QPushButton and implement your own right click handling. Here is a working example (I didn't test it thoroughly, so there might be some problems):

#include <QApplication>
#include <QPushButton>
#include <QMouseEvent>
#include <QLayout>
#include <QDebug>

class CustomButton : public QPushButton
{
    Q_OBJECT
public:
    explicit CustomButton(QWidget *parent = 0) : QPushButton(parent){}

protected:
    void mousePressEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::RightButton && hitButton(e->pos()))
        {
            setDown(true);
            emit pressed();
        }
        QPushButton::mousePressEvent(e);
    }

    void mouseMoveEvent(QMouseEvent *e)
    {
        if(e->buttons() & Qt::RightButton)
        {
            if(hitButton(e->pos()) != isDown())
                setDown(!isDown());
        }
        QPushButton::mouseMoveEvent(e);
    }

    void mouseReleaseEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::RightButton)
        {
            setDown(false);
            if(hitButton(e->pos()))
                click();
        }
        QPushButton::mouseReleaseEvent(e);
    }
};

void buttonClicked()
{
    qDebug() << "CLICKED";
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.resize(500,500);
    w.setLayout(new QVBoxLayout);
    CustomButton button;
    button.setAutoRepeat(true);
    QObject::connect(&button, &CustomButton::clicked, &buttonClicked);
    w.layout()->addWidget(&button);
    w.show();

    return a.exec();
}

#include "main.moc"

If you want to differentiate between the right click and the left click, then see the source code for QAbstractButton::click, and implement your own for the right click.

thuga
  • 12,601
  • 42
  • 52
  • Actually, using an event filter is one idiomatic approach to adding behavior to a `QWidget` :) – Kuba hasn't forgotten Monica Aug 30 '16 at 13:52
  • Thanks. It solved my problem to some extent. But I am yet to get AutoRpeat feature from the right button press event. Can you please be kind enough to point me how to do that? Thanks in advance. – rugi Aug 31 '16 at 04:46
  • @KubaOber Sure. I just find this way to be prettier :) – thuga Aug 31 '16 at 06:14
  • @rugi In the example I provided auto repeat is working. When I hold the right mouse button down, the `"CLICKED"` message is constantly printed out. – thuga Aug 31 '16 at 06:15
  • @thuga Yes its working. There was a mistake from my side. Thanks for your help. – rugi Aug 31 '16 at 07:43
0

You can implement the functionality in an event filter, and install it on the button(s) you want to be right-clickable.

// https://github.com/KubaO/stackoverflown/tree/master/questions/right-to-left-event-39220180
#include <QtWidgets>

class RightToLeftClick : public QObject {
    bool eventFilter(QObject *watched, QEvent *event) {
        if (event->type() == QEvent::MouseButtonDblClick ||
                event->type() == QEvent::MouseButtonPress ||
                event->type() == QEvent::MouseButtonRelease) {
            auto ev = static_cast<QMouseEvent*>(event);
            if (ev->button() == Qt::RightButton) {
                auto buttons = ev->buttons();
                if (buttons & Qt::RightButton) {
                    buttons ^= Qt::RightButton;
                    buttons |= Qt::LeftButton;
                }
                QMouseEvent lev{ev->type(),
                            ev->localPos(),
                            ev->windowPos(),
                            ev->screenPos(),
                            Qt::LeftButton,
                            buttons,
                            ev->modifiers(),
                            ev->source()};
                Q_ASSERT(! (lev.buttons() & Qt::RightButton));
                QCoreApplication::sendEvent(watched, &lev);
                return true;
            }
        }
        return QObject::eventFilter(watched, event);
    }
public:
    explicit RightToLeftClick(QObject * parent = nullptr) : QObject{parent} {
        addTo(parent);
    }
    void addTo(QObject * obj) {
        if (obj) obj->installEventFilter(this);
    }
};

Here's how to use it:

int main(int argc, char ** argv) {
    QApplication app{argc, argv};
    QWidget ui;
    QVBoxLayout layout{&ui};
    QPushButton button1{"Left Click Me"};
    QPushButton button2{"Right Click Me"};
    layout.addWidget(&button1);
    layout.addWidget(&button2);
    ui.show();
    RightToLeftClick rtl{&button2};
    return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thanks. But I am yet to get AutoRpeat feature from the right button press event. Can you please be kind enough to point me how to do that? Thanks in advance. – rugi Aug 31 '16 at 04:47
  • I guess you haven't tried this code, then. The autorepeat works fine under Qt 5.7. Of course you need to `setAutoRepeat` on the button! – Kuba hasn't forgotten Monica Aug 31 '16 at 12:21