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