Qt 事件模块有一个强大的特性,就是可以设置一个QObject1 的实例可以实时的去监测另一个QObject2的实例的事件,在被监测控件QObject2能看到事件之前,就先被监测的控件QObject看到(拦截)并处理。
例如这样一个场景,在一个QDialog里有一个QLabel显示一张图片,我们想要双击(double clicked )这个图片QLabel然后就关闭这个QDialog。
正常情况下,一个QLabel是没有直接的响应双击的信号的,这时候我们就需要监测这个QLabel响应的双击事件了。
那么该怎样做呢?
1.首先在QDialog的头文件.h中,声明
#ifndef DETAILPIC_H #define DETAILPIC_H #include <QDialog> namespace Ui { class DetailPic; } class DetailPic : public QDialog { Q_OBJECT public: explicit DetailPic(QWidget *parent = 0); void loadImage(const QString &filePath); ~DetailPic(); protected: bool eventFilter(QObject *, QEvent *); private: Ui::DetailPic *ui; }; #endif // DETAILPIC_H
这里面主要是protected中的 eventFilter()函数。
bool eventFilter(QObject *obj, QEvent *ev);
解释一下这个函数,这是被事件过滤器,就是所有被QDialog监测的控件,发生的所有事件都会先执行这个函数。obj为被监测的控件, ev是事件。
2.在QDialog的.cpp文件中 构造函数中首先要给被监测的控件安装事件过滤器。
ui->picLabel->installEventFilter(this);
这个函数就是安装事件过滤器,ui->picLabel为被监测的控件, 参数this表示谁要监测ui->picLabel的事件。因为我们是想这个QDialog控件来监视picLabel这个控件,所以参数为this.
3.实现函数bool eventFilter(QObject *obj, QEvent *ev)
bool DetailPic::eventFilter(QObject *obj, QEvent *evn) { if(obj == ui->picLabel) { if(evn->type() == QEvent::MouseButtonDblClick) { this->reject(); return true; //事件到此为止,不再需要其他来处理了。 } } return QDialog::eventFilter(obj, evn); // 事件继续广播出去,按照普通的方式去处理这个事件。 }
这个函数的参数obj为被监视的控件,ev为发生的事件。
给出所有代码
#include "DetailPic.h" #include <QNetworkAccessManager> #include <QNetworkReply> #include <QtWidgets> #include <DetailPic.h> #include "ui_Detailpic.h" DetailPic::DetailPic(QWidget *parent) : QDialog(parent), ui(new Ui::DetailPic) { ui->setupUi(this); setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); setAttribute(Qt::WA_TranslucentBackground); ui->picLabel->installEventFilter(this); } void DetailPic::loadImage(const QString &filePath) { QUrl url(filePath); QNetworkAccessManager manager; QEventLoop loop; QNetworkReply *reply = manager.get(QNetworkRequest(url)); //请求结束并下载完成后,退出子事件循环 connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); //开启子事件循环 loop.exec(); QByteArray jpegData = reply->readAll(); QPixmap pixmap; pixmap.loadFromData(jpegData); ui->picLabel->setPixmap(pixmap); this->resize(pixmap.width(),pixmap.height()); } DetailPic::~DetailPic() { delete ui; } bool DetailPic::eventFilter(QObject *obj, QEvent *evn) { if(obj == ui->picLabel) { if(evn->type() == QEvent::MouseButtonDblClick) { this->reject(); return true; } } return QDialog::eventFilter(obj, evn);; }