QPushButton中的鼠标右键功能

时间:2016-08-30 06:24:42

标签: qt

我想从鼠标的右键保持所有左键,在QPushButton上实现鼠标左键的所有功能(如clicked(),pressed(),release(),setAutoRepeat())功能完好。以下是重新实现eventFilter的代码,它没有给出理想的结果。

class object : public boost::enable_shared_from_this<object> {
public:
    object()
    : service(new boost::asio::io_service),
    work(new boost::asio::io_service::work(*service)),
    strand(*service),
    value(0) {}

    void workerThread() {
        service->run();
    }

    void run() {
        func_int = strand.wrap(boost::bind(&object::handler_int, shared_from_this(), _1));
        func_void = strand.wrap(boost::bind(&object::handler_void, shared_from_this()));

        std::thread thread(boost::bind(&object::workerThread, this));

        func_int(1);
        func_int(1);

        func_void();
        func_void();    // Will crash due to shared_ptr being NULL, hence "value" cannot be accessed in handler_void

        thread.join();
    }

    void handler_int(int parameter) {
        cout << "handler_int: " << value << endl;
    }

    void handler_void() {
        cout << "handler_void: " << value << endl;
    }

    boost::shared_ptr<boost::asio::io_service> service;
    boost::shared_ptr<boost::asio::io_service::work> work;
    boost::asio::strand strand;
    std::function<void(int)> func_int;
    std::function<void(void)> func_void;
    int value;
};


int main(int argc, char *argv[]) {    
    boost::shared_ptr<object> obj(new object());
    obj->run();
    return 0;
}

任何人都可以帮忙吗?提前谢谢。

2 个答案:

答案 0 :(得分:2)

您不应该为此使用事件过滤器。子类QPushButton并实现您自己的右键单击处理。这是一个工作示例(我没有彻底测试它,因此可能存在一些问题):

#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"

如果要区分右键单击和左键单击,请参阅source code for QAbstractButton::click,并实现自己的右键单击。

答案 1 :(得分:0)

您可以在事件过滤器中实现该功能,并将其安装在您想要可右键单击的按钮上。

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

以下是如何使用它:

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