我们可以把Qt的事件传递看成链状:如果子类没有处理这个事件,就会继续向其父类传递
1.新建一个myButton类,将其基类改为QPushButton.
2.在ui中新建一个Push Button控件,并将其提升为myButton.
3.在mybutton.h中增加鼠标按下事件.
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QWidget>
#include<QPushButton>
class myButton : public QPushButton
{
Q_OBJECT
public:
explicit myButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *ev);
signals:
};
#endif // MYBUTTON_H
4.在mybutton.cpp中实现鼠标按下事件.
注意观察有和没有else时的执行结果!!
void myButton::mousePressEvent(QMouseEvent *ev)
{
if(ev->button()==Qt::LeftButton)
{
qDebug()<<"按下的是左键";
//事件的接收,如果这里按下的是左键,事件不再继续传递!!(Qt不会再去寻找其他的接受者,那么父类的操作也就不能进行,这可能会有潜在的危险)
//ev->ignore();//执行ignore()后事件会继续传递,传递给谁呢?这里注意,是传递给父组件,不是父类!!
}
else//注意观察有和没有else时的执行结果!!
{
QPushButton::mousePressEvent(ev);
//事件的忽略,这里如果按下的不是左键,事件继续传递给父类去处理
}
}
mywidget.cpp:
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MyWidget)
{
ui->setupUi(this);
connect(ui->pushButton,&QPushButton::released,//事件传递给父类处理,这样在QPushButton::mousePressEvent(ev)就会发射信号,从而执行当前这句!!!
[=]()
{
qDebug()<<"QPushButton::released";
}
);
}
ignore()函数:
可见,这个名字为pushButton的控件的父组件是MyWidget,父类是myButton.
所以执行 ev->ignore();
后事件会继续传递,传递给父组件,不是父类!!
可以进行如下验证:
在mywidget.h中增加一个鼠标按下事件:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
~MyWidget();
protected:
//鼠标按下事件
void mousePressEvent(QMouseEvent *ev);
private:
Ui::MyWidget *ui;
};
在mywidget.cpp中
void MyWidget::mousePressEvent(QMouseEvent *ev)
{
qDebug()<<"MyWidget::mousePressEvent";
}
在mybutton.cpp中
void myButton::mousePressEvent(QMouseEvent *ev)
{
if(ev->button()==Qt::LeftButton)
{
qDebug()<<"按下的是左键";
ev->ignore();
}
else
{
QPushButton::mousePressEvent(ev);
}
}
运行结果:
这就说明了执行 ev->ignore();
后事件会继续传递给父组件,不是父类!
事实上,我们很少使用accept()和ignore()函数,而是像上面的示例一样,如果希望忽略事件,只要调用父类的响应函数即可。Qt中的事件大部分是protected的,因此,重写的函数必定存在着其父类中的响应函数,这个方法是可行的。
而accept()和ignore()函数的正确用法是用在重写CloseEvent函数中。见示例:
void MyWidget::closeEvent(QCloseEvent *event)
{
int ret = QMessageBox::question(this,"question","是否要关闭窗口");
if(ret == QMessageBox::Yes){
event->accept();
}else if(ret == QMessageBox::No){
event->ignore();//继续传递给它的父组件
}
}
这个事件所在的操作就是关闭窗口。因此,一旦接受事件,窗口就会被关闭;否则窗口继续保留。