QPushButton的鼠标事件处理及EventFilter事件过滤器的用法

xiaoxiao2021-02-27  378

        这两天在做一个软键盘,支持QLineEdit的输入,原来都是处理的keyPressEvent,现在用的是mousePressEvent,移植原来的代码居然不行。折腾了半天发现,QPushButton自身会处理到鼠标左键的单击事件,即使你用了事件过滤器也不行!具体验证了三种情况:

(1)QPushButton类会处理鼠标左键单击事件,不会再向父窗口传递,父窗口的eventFilter也无法捕捉这个事件。

(2)同在一个窗口的QLabel可以在父窗口eventFilter被捕捉

(3)继承QPushButton重新实现鼠标事件,还是不能被eventFilter捕捉,但是这样可以独立处理鼠标单击事件。

代码如下,有两种情况可以根据if、else进行选择编译:

1.dailog.h

#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> #if 0 class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); bool eventFilter(QObject *obj, QEvent *event); void mousePressEvent(QMouseEvent *event); //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 void mouseReleaseEvent(QMouseEvent *event); //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 }; #else class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); bool eventFilter(QObject *obj, QEvent *event); void mousePressEvent(QMouseEvent *event); //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 }; class myButton : public QPushButton { Q_OBJECT public: myButton(QWidget *parent = 0); myButton(const QString & text, QWidget *parent = 0); ~myButton(); void mousePressEvent(QMouseEvent *event); //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 void mouseReleaseEvent(QMouseEvent *event); //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 }; #endif #endif // DIALOG_H

2.dialog.cpp

#include "dialog.h" #include <QPushButton> #include <QDebug> #include <QEvent> #include <QKeyEvent> #include <QLabel> /******************************************************************** * QPushButton本身就相应鼠标的左键的单击事件!!!!! * 以下是两种情况来验证qt事件过滤器对于QPustButton的鼠标事件的影响: * 1.直接使用QPushButton类; * 2.继承QPushButton类,重写mousePressEvent、mouseReleaseEvent事件。 ********************************************************************/ #if 0 /*运行程序,分别点击QPushButton按钮、QLabel按钮,通过打印可以看出事件过滤器对QPushButton的鼠标事件无法过滤,同在一 * 个窗口的QLabel鼠标事件却能够过滤,可见QPushButton对于鼠标事件进行了直接处理,过滤器无法拦截;QLabel的鼠标事件则可 * 以进行拦截。*/ Dialog::Dialog(QWidget *parent) : QDialog(parent) { QPushButton *btn = new QPushButton("QPushButton", this); btn->resize(100,50); btn->move(100,50); QLabel *label = new QLabel("QLabel", this); label->setStyleSheet("border:2px solid green;border-radius: 3px;background: #EEEEEE"); label->resize(100, 50); label ->move(100,150); //事件过滤器用法:A->installEventFilter(B)表示通过B中定义的事件过滤器来监控A,A是被监控者! this->installEventFilter(this); resize(300, 300); } Dialog::~Dialog() {} bool Dialog::eventFilter(QObject *obj, QEvent *event) { //qDebug()<<"Dialog::eventFilter"<<event->type(); if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { qDebug()<<"Dialog::eventFilter received mouse event!"<<event->type(); //return true,不让它继续传递了,这样Dialog::mousePressEvent()就不会有打印; //return false,事件将接着被送往剩下的事件过滤器或是目标对象进行处理,Dialog::mousePressEvent()有打印 return false; } return QObject::eventFilter(obj, event); //按照默认的处理方式继续传递 } void Dialog::mousePressEvent(QMouseEvent *event) //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 { qDebug()<<"Dialog::mousePressEvent"<<event->type(); } void Dialog::mouseReleaseEvent(QMouseEvent *event) //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 { qDebug()<<"Dialog::mouseReleaseEvent"<<event->type(); } #else Dialog::Dialog(QWidget *parent) : QDialog(parent) { myButton *btn = new myButton("Button",this); btn->resize(100,50); btn->move(100,50); this->installEventFilter(this); resize(300, 300); } Dialog::~Dialog() {} bool Dialog::eventFilter(QObject *obj, QEvent *event) { //qDebug()<<"Dialog::eventFilter"<<event->type(); if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { qDebug()<<"Dialog::eventFilter received mouse event!"<<event->type(); } return QObject::eventFilter(obj, event); } void Dialog::mousePressEvent(QMouseEvent *event) { qDebug()<<"Dialog::mousePressEvent"<<event->type(); } //下面的QPushButton(text, parent)是在初始化列表中调用了基类的构造函数对基类对象进行初始化,因为构造子类时,基类构造函数 //先要被调用,基类有两个构造函数QPushButton(const QString & text, QWidget * parent = 0)和QPushButton(QWidget * parent = 0) //我测试了下,随便你初始化哪个都行,但是如果用第二个就只能在构造函数里设置文本信息。 //关于利用列表初始化中调用基类构造具体可以参考:http://blog.csdn.net/bdss58/article/details/40348901 myButton::myButton(QWidget *parent):QPushButton(parent){} //这样可以的 //myButton::myButton(QWidget *parent):QPushButton("Button", parent) {}//这样居然也是可以的 myButton::myButton(const QString & text, QWidget *parent ): QPushButton(text, parent)//还是这个方便 { } myButton::~myButton() { } void myButton::mousePressEvent(QMouseEvent *event) //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 { qDebug()<<"myButton::mousePressEvent"<<event->type(); } void myButton::mouseReleaseEvent(QMouseEvent *event) //注意这里不要写成(QKeyevent *event),否则接收不到鼠标事件 { qDebug()<<"myButton::mouseReleaseEvent"<<event->type(); } #endif

3.main.cpp

#include "dialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }

注释很详细,不再赘述!

不错的参考资料:

QT父子窗口事件传递与事件过滤器

浅谈Qt事件的路由机制:鼠标事件

为什么鼠标左击事件不响应呢?

转载请注明原文地址: https://www.6miu.com/read-2700.html

最新回复(0)