Qt的事件模型中提供的事件过滤器功能使得一个QObject对象可以监视另一个QObject对象中的事件,通过在一个QObject对象中安装事件过滤器,可以在事件到达该对象前捕获事件,从而起到监视该对象事件的作用。
例如,Qt已经提供了QPushButton用于表示一个普通的按钮类。如果需要实现一个动态的图片按钮,即当鼠标键按下时按钮图片发生变化,则需要同时响应鼠标按下等事件。
本文实例通过事件过滤器实现动态图片按钮效果,如图所示。三个图片分别对应三个QLabel对象。当用鼠标键按下某个图片时,图片大小会发生变化;而释放鼠标键时,图片又恢复初始大小,并且程序将提示当前事件的状态信息,如鼠标键类型、被鼠标键按下的图片序号等。
具体实现步骤如下。
步骤一
头文件“eventfilter.h”中声明了所需的各种控件及槽函数,其具体代码如下:
#include <QDialog>
#include <QLabel>
#include <QImage>
#include <QEvent>
class EventFilter : public QDialog
{
Q_OBJECT
public:
EventFilter(QWidget *parent = nullptr);
~EventFilter();
public slots:
bool eventFilter(QObject *, QEvent *);
private:
QLabel *label1;
QLabel *label2;
QLabel *label3;
QLabel *stateLabel;
QImage Image1;
QImage Image2;
QImage Image3;
};
其中,eventFilter()函数是QObject的事件监视函数。
步骤二
源文件“eventfilter.cpp”的具体代码如下:
#include "eventfilter.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
EventFilter::EventFilter(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("事件过滤"));
label1 = new QLabel;
Image1.load("../image/1.png");
label1->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
label1->setPixmap(QPixmap::fromImage(Image1));
label2 = new QLabel;
Image2.load("../image/2.png");
label2->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
label2->setPixmap(QPixmap::fromImage(Image2));
label3 = new QLabel;
Image3.load("../image/3.png");
label3->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
label3->setPixmap(QPixmap::fromImage(Image3));
stateLabel = new QLabel(tr("鼠标按下标志"));
stateLabel->setAlignment(Qt::AlignHCenter);
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label1);
layout->addWidget(label2);
layout->addWidget(label3);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(layout);
mainLayout->addWidget(stateLabel);
label1->installEventFilter(this);
label2->installEventFilter(this);
label3->installEventFilter(this);
}
其中,installEventFilter()函数为每一个图片安装事件过滤器,指定整个窗体为监视事件的对象,函数原型如下:
void QObject::installEventFilter(QObject *filterObj)
参数filterObj是监视事件的对象,此对象可以通过eventFilter()函数接收事件。如果某个事件需要被过滤,即停止正常的事件响应,则在eventFilter()函数中返回true,否则返回false。QObject的removeEventFilter()函数可以解除己安装的事件过滤器。
步骤三
QObject的事件监视函数eventFilter()的具体实现代码如下:
bool EventFilter::eventFilter(QObject *watched, QEvent *event)
{
bool islabel=false;
QLabel *curlab;
QString curName;
QImage *curImage;
QString className=watched->metaObject()->className();
if(className=="QLabel"){
islabel=true;
curlab=(QLabel *)watched;
if(curlab==label1){ //首先判断当前发生事件的对象
curName="左边图片";
curImage=&Image1;
}else if(curlab==label2){
curName="中间图片";
curImage=&Image2;
}else if(curlab==label3){
curName="右边图片";
curImage=&Image3;
}
//判断发生的事件类型
if(event->type()==QEvent::MouseButtonPress)
{
//将事件event转化为鼠标事件
QMouseEvent *mouseEvent=(QMouseEvent *)event;
/* 以下根据鼠标的按键类型分别显示 */
if(mouseEvent->buttons()&Qt::LeftButton){
stateLabel->setText("左键按下"+curName);
}else if(mouseEvent->buttons()&Qt::MiddleButton){
stateLabel->setText("中键按下"+curName);
}else if(mouseEvent->buttons()&Qt::RightButton){
stateLabel->setText("右键按下"+curName);
}
/* 显示缩小的图片 */
QTransform transform;
transform.scale(1.8,1.8);
QImage tmpImg = curImage->transformed(transform);
curlab->setPixmap(QPixmap::fromImage(tmpImg));
}
/* 鼠标释放事件的处理,恢复图片的大小 */
if(event->type()==QEvent::MouseButtonRelease){
stateLabel->setText("鼠标释放"+curName);
curlab->setPixmap(QPixmap::fromImage(*curImage));
}
}
//将事件交给上层对话框
return QDialog::eventFilter(watched,event);
}
最后,运行结果如图所示。
————————————————
觉得有用的话请关注点赞,谢谢您的支持!
对于本系列文章相关示例完整代码有需要的朋友,可关注并在评论区留言!