您的位置:首页 > 编程语言 > Qt开发

Qt的事件处理机制分析

2014-06-07 22:35 447 查看
转自:http://blog.csdn.net/digu/article/details/1801074

如果对MFC有点了解,可以近似的把Qt的信号(signal)和事件(event)对应于MFC的命令(command)和消息(message) ,事件是窗口系统或者qt对不同情况的响应,绝大多数被产生的事件都是对用户行为的响应,但是也有一些,比如定时器事件,它们是被系统独立产生的。QWidget::event()虚函数是各种事件的一个大管家,负责把大多数常用类型的事件传递给特定的事件处理器(事件处理函数,也都是虚拟函数,便于其继承子类对于该事件处理的编程),可以分析一下事件总管QWidget::event()虚函数的部分源码(完整源码在C:/Qt/4.2.2/src/gui/kernel/qwidget.cpp中qwidget::event()函数的定义):

QEvent类实现对事件的封装。The QEvent class is the base class of all event classes. Event objects contain event
parameters.

bool QWidget::event(QEvent *event)

{

Q_D(QWidget);

// ignore mouse events when disabled

if (!isEnabled()) {

switch(event->type()) {

case QEvent::TabletPress:

case QEvent::TabletRelease:

case QEvent::TabletMove:

case QEvent::MouseButtonPress:

case QEvent::MouseButtonRelease:

case QEvent::MouseButtonDblClick:

case QEvent::MouseMove:

case QEvent::ContextMenu:

#ifndef QT_NO_WHEELEVENT

case QEvent::Wheel:

#endif

return false;

default:

break;

}

}

switch (event->type()) { //判断事件类型

case QEvent::MouseMove:

mouseMoveEvent((QMouseEvent*)event); //将鼠标移动类型的事件分派给mouseMoveEvent函数处理

break;

case QEvent::MouseButtonPress:

// Don't reset input context here. Whether reset or not is

// a responsibility of input method. reset() will be

// called by mouseHandler() of input method if necessary

// via mousePressEvent() of text widgets.

#if 0

resetInputContext();

#endif

mousePressEvent((QMouseEvent*)event);

break;

case QEvent::MouseButtonRelease:

mouseReleaseEvent((QMouseEvent*)event);

break;

case QEvent::MouseButtonDblClick:

mouseDoubleClickEvent((QMouseEvent*)event);

break;

#ifndef QT_NO_WHEELEVENT

case QEvent::Wheel:

wheelEvent((QWheelEvent*)event);

break;

#endif

……

……

然后在需要处理该事件的QWidget派生类中重写响应的事件处理函数(覆盖默认的虚函数,如event,keyPressEvent等函数)来完成在该派生类对象中对该事件的响应。

关于对事件过滤器的编程,一般分两步:

1、通过对目标对象(被监视对象)调用installEventFilter()函数来注册监视对象;

2、在监视对象的eventFilter函数中处理目标对象的事件。(可以认为监视对象拦截了目标对象的事件)

下面用代码来说明事件处理处理和事件过滤:

//newlineedit.h

#ifndef NEWLINEEDIT_H

#define NEWLINEEDIT_H

#include <QLineEdit>

#include "ui_newlineedit.h"

class newLineEdit : public QLineEdit

{

Q_OBJECT

public:

newLineEdit(QWidget *parent = 0);

~newLineEdit();

bool event(QEvent *event); //重写event虚函数来处理特定的事件

private:

Ui::newLineEditClass ui;

};

#endif // NEWLINEEDIT_H

//www.h

#ifndef WWW_H

#define WWW_H

#include <QtGui/QMainWindow>

#include "ui_www.h"

class www : public QMainWindow

{

Q_OBJECT

public:

www(QWidget *parent = 0, Qt::WFlags flags = 0);

~www();

bool eventFilter(QObject *target, QEvent *event); //重写eventFilter虚函数来拦截特定的事件

private:

Ui::wwwClass ui;

};

#endif // WWW_H

//newlineedit.cpp

#include "newlineedit.h"

#include <QKeyEvent>

newLineEdit::newLineEdit(QWidget *parent)

: QLineEdit(parent)

{

ui.setupUi(this);

}

bool newLineEdit::event(QEvent *event)

{

if (event->type() == QEvent::KeyPress)

{

QKeyEvent *keyEvent = (QKeyEvent *)event;

if (keyEvent->key() == Qt::Key_Tab) //判断特定的事件,作出自定义的处理

{

insert("/t");

return true;

}

}

return QWidget::event(event); //将不需要特定处理的事件交给默认的基类event()函数处理

}

newLineEdit::~newLineEdit()

{

}

//www.cpp

#include "www.h"

#include <QKeyEvent>

www::www(QWidget *parent, Qt::WFlags flags)

: QMainWindow(parent, flags)

{

ui.setupUi(this);

ui.lineEdit->installEventFilter(this); //注册this监视ui.lineEdit对象,this拦截ui.lineEdit的某些事件

bool www::eventFilter(QObject *target, QEvent *event)

{

if (target == ui.lineEdit && event->type() == QEvent::KeyPress

&& ((QKeyEvent *)event)->key() == Qt::Key_Tab) //判断监视拦截条件是否满足,如是,则拦截该事件

{

ui.lineEdit->insert(tr("filter completed!"));

return true;

}

return QMainWindow::eventFilter(target, event);

}

www::~www()

{

}

然后我们再来分析一下QObject::installEventFilter函数的源码,看其是如何实现过滤功能的:

void QObject::installEventFilter(QObject *obj)

{

Q_D(QObject);

if (!obj)

return;

QWriteLocker locker(QObjectPrivate::readWriteLock());

// clean up unused items in the list

d->eventFilters.removeAll((QObject*)0);

d->eventFilters.removeAll(obj);

d->eventFilters.prepend(obj);

}

可以参考下一篇分析QObject的文章.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: