`
soboer
  • 浏览: 1311858 次
文章分类
社区版块
存档分类
最新评论

QT编程----事件(二)

 
阅读更多

eventFilter事件过滤器

Qt事件模型一个真正强大的特色是一个QObject的实例能够管理另一个QObject实例的事件。

一个CustomerDialog的小部件。CustomerDialog包含一系列QLineEdit.现在,我们想用空格键来代替Tab,使焦点在这些QLineEdit间切换。

一个解决的方法是子类化QLineEdit,重新实现keyPressEvent(),并在keyPressEvent()里调用focusNextChild()。像下面这样:

voidMyLineEdit::keyPressEvent(QKeyEvent*event)

{

if(event->key()==Qt::Key_Space){

focusNextChild();

}else{

QLineEdit::keyPressEvent(event);

}

}

上述做法有一个缺点。如果CustomerDialog里有很多不同的控件(比如QComboBox,QEdit,QSpinBox),我们就必须子类化这么多控件。这是一个烦琐的任务。

一个更好的解决办法是:让CustomerDialog去管理他的子部件的按键事件,实现要求的行为。我们可以使用事件过滤器。

一个事件过滤器的安装需要下面2个步骤:

1,调用installEventFilter()注册需要管理的对象。

2,在eventFilter()里处理需要管理的对象的事件。

一般,推荐在CustomerDialog的构造函数中注册被管理的对象。像下面这样:

CustomerInfoDialog::CustomerInfoDialog(QWidget*parent):QDialog(parent)

{...

firstNameEdit->installEventFilter(this);

lastNameEdit->installEventFilter(this);

cityEdit->installEventFilter(this);

phoneNumberEdit->installEventFilter(this);

}

一旦,事件管理器被注册,发送到firstNameEditlastNameEditcityEditphoneNumberEdit的事件将首先发送到eventFilter()

下面是一个eventFilter()函数的实现:

boolCustomerInfoDialog::eventFilter(QObject*target,QEvent*event)

{

if(target==firstNameEdit||target==lastNameEdit

||target==cityEdit||target==phoneNumberEdit){

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

QKeyEvent*keyEvent=static_cast<QKeyEvent*>(event);

if(keyEvent->key()==Qt::Key_Space){

focusNextChild();

returntrue;

}

}

}

returnQDialog::eventFilter(target,event);

}

在上面的函数中,我们首先检查目标部件是否是firstNameEditlastNameEditcityEditphoneNumberEdit。接着,我们判断事件是否是按键事件。如果事件是按键事件,我们把事件转换为QKeyEvent。接着,我们判断是否按下了空格键,如果是,我们调用focusNextChild(),把焦点传递给下一个控件。然后,返回,true通知Qt,我们已经处理了该事件。

如果返回false的话,Qt继续将该事件发送给目标控件,结果是一个空格被插入到QLineEdit中。

如果目标控件不是QLineEdit,或者按键不是空格键,我们将把事件传递给基类的eventFilter()函数。

Qt提供5个级别的事件处理和过滤:

1,重新实现事件函数。比如:mousePressEvent(),keyPress-Event(),paintEvent()。这是最常规的事件处理方法。

2,重新实现QObject::event().

这一般用在Qt没有提供该事件的处理函数时。也就是,我们增加新的事件时。

3,安装事件过滤器

4,在QApplication上安装事件过滤器。

QApplication上的事件过滤器将捕获应用程序的所有事件,而且第一个获得该事件。也就是说事件在发送给其它任何一个eventfilter之前发送给QApplicationeventfilter

5,重新实现QApplicationnotify()方法.

Qt使用notify()来分发事件。要想在任何事件处理器捕获事件之前捕获事件,唯一的方法就是重新实现QApplicationnotify()方法。

在创建了过滤器之后,下面要做的是安装这个过滤器。安装过滤器需要调用installEventFilter()函数。这个函数的签名如下:

 voidQObject::installEventFilter(QObject*filterObj)

这个函数是QObject的一个函数,因此可以安装到任何QObject的子类,并不仅仅是UI组件。这个函数接收一个QObject对象,调用了这个函数安装事件过滤器的组件会调用filterObj定义的eventFilter()函数。

例如,textField->installEventFilter(obj),则如果有事件发送到textField组件是,会先调用obj->eventFilter()函数,然后才会调用textField->event()

也可以把事件过滤器安装到QApplication上面,这样就可以过滤所有的事件,已获得更大的控制权。不过,这样做的后果就是会降低事件分发的效率。

如果一个组件安装了多个过滤器,则最后一个安装的会最先调用,类似于堆栈的行为。

pushButton2=newQPushButton(this,"pushButton2");

pushButton2->setGeometry(QRect(200,160,111,31));

pushButton2->installEventFilter(this);

boolForm1::eventFilter(QObject*o,QEvent*e)

{

if(pushButton2==o)

{

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

{

QKeyEvent*k=(QKeyEvent*)e;

qDebug("eatkeypress%d",k->key());

returnTRUE;

}

if(e->type()==QEvent::MouseButtonPress)

{

QMouseEvent*k=(QMouseEvent*)e;

qDebug("eatMousepress");

returnTRUE;

}

else{

returnFALSE;

}

}

else

returnQWidget::eventFilter(o,e);

}

boolForm1::event(QEvent*event)

{

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

{

QKeyEvent*keyEvent=(QKeyEvent*)event;

if(keyEvent->key()==Key_A)

{

qDebug("--cuttheKey_A--\n");

returntrue;

}

}

returnQWidget::event(event);

}

事件的产生

QT应用程序可以产生自定义的事件,或是预定义类型,或是自定义类型。这可以通过创建QEvent类或它的子类的实例,并且调用QApplication:postEvent()QApplication::sendEvent()来实现。

这两个函数需要一个QObject*与一个QEvent*作为参数,假如你调用postEvent(),你必须用new操作符来创建事件对象,Qt会它被处理后帮你删除它。

假如你用sendEvent(),你应该在栈上来创建事件。

下面举两个例子:

一是posting事件:

QApplication::postEvent(mainWin,new

QKeyEvent(QEvent::KeyPress,Key_X,'X',0,"X"));

二是sending事件:

QKeyEventevent(QEvent::KeyPress,Key_X,'X',0,"X");

QApplication::sendEvent(mainWin,&event);

Qt应用程序很少直接调用postEvent()或是sendEvnet(),因为大多数事件会在必要时被Qt或是窗口系统自动产生。在大多数的情况下,当你想发送一个事件时,Qt已经为你准备好了一个更高级的函数来为你服务。(例如update()repaint())

为了提高qt程序的自定义特性,可以显式得采用程序实现事件的发送。

重绘事件paintEvent()

当窗口被其他窗口覆盖后,再次重新显示时,系统将产生spontaneous事件来请求重绘,事件循环最终从事件队列中捡选这个事件并把它分发到那个需要重画的widget

当我们调用QWidget::update()时,产生的是Posted重绘事件

当我们调用QWidget::repaint()时,产生的是Sent重绘事件

posting相对于sending的一个优势是,它给了Qt一个压缩(compress)事件的机会。假如你在一个widget上连续地调用update()十次,因update()而产生的这十个事件,将会自动地被合并为一个单独的事件,但是QPaintEvents事件附带的区域信息也合并了。

可压缩的事件类型包括:paint,move,resize,layouthint,languagechange

最后要注意,可以在任何时候调用QApplication::sendPostedEvent(),强制Qt产生一个对象的posted事件。

Qt系统还提供了一个QCustomEvent类,用于用户自定义事件,这些自定义事件可以利用QThread::postEvent()或者QApplication::postEvent()被发给各种控件或其他QObject实例。

QWidget类的子类可以通过QWidget::customEvent()事件处理函数方便地接收到这些自定义的事件。

需要注意的是:QCustomEvent对象在创建时都带有一个类型标识id以定义事件类型,为了避免与Qt系统定义的事件类型冲突,该id值应该大于枚举类型QEvent::Type中给出的"User"值。

演示如何post一个定制事件的代码片段:

constQEvent::TypeMyEvent=(QEvent::Type)1234;

...

QApplication::postEvent(mainwin,newQCustomEvent(MyEvent));

事件必须是QCustomEvent类型(或子类)的。

构造函数的参数是事件的类型,1000以下被Qt保留。其他可被程序使用。为处理定制事件类型,要重新实现customEvent()函数:

voidMyWin::customEvent(QCustomEvent*event)

{

if(event->type()==MyEvent){

myEvent();

}else{

Qwidget::customEvent(event);

}

}

QcustomEvent类有一个void*的成员,可用于特定的目的。你也可以子类化QCustomEvent,加上别的成员。

一些事件类型可以被传递。这意味着假如目标对象不处理一个事件,Qt会试着寻找另外的事件接收者。用新的目标来调用QApplication::notify()

举例来讲,key事件是传递的,假如拥有焦点的Widget不处理特定键,Qt会分发相同的事件给父widget,然后是父亲的父亲,直到最顶层widget

可被传递的事件可以接收或是忽略这个事件。假如事件被处理,这个事件将不会再被传递。否则Qt会试着查找另外的事件接收者。

大部分qt对象对事件的处理缺省情况下是接收,在QWidget中的缺省实现是调用忽略”,假如你希望接收事件,你需要做的是重新实现事件handler,避免调用QWidget的实现。假如你想忽略事件,只需简单地传递它到QWidget的实现。

下面的代码演示了这一点:

voidMyWidget::keyPressEvent(QKeyEvent*event)

{

if(event->key()==Key_Escape){

doEscape();

}else{

QWidget::keyPressEvent(event);

}

}

在上面的例子里,假如用户按了"ESC"键,我们会调用doEscape()并且事件被接收了(这是缺省的情况),事件不会被传递到父widget,假如用户按了别的键,则调用QWidget的缺省实现。

voidQWidget::keyPressEvent(QKeyEvent*event)

{

event->ignore();

}

此处调用ignore(),事件会被传递到父widget中去。

以上假设基类都是QWidget,然而,同样的规则也可以应用到别的层次中,只要用其他基类代替QWidget即可。

举例来说:

voidMyLineEdit::keyPressEvent(QKeyEvent*event)

{

if(event->key()==Key_SysReq){

doSystemRequest();

}else{

QLineEdit::keyPressEvent(event);

}

}

分享到:
评论

相关推荐

    QT编程----事件

    QT编程----事件(一). 事件的反应 点击按钮弹出事件框

    QT编程手册----QT编程手册---学习QT的C++编程

    学习轻量级C++的GUI编程 不想多说,想学就下。

    Qt编程-QTableView同时冻结行和列

    Qt编程-QTableView同时冻结行和列 https://lcxing.blog.csdn.net/article/details/133745138 示例代码

    Qt编程-QTableView冻结行或冻结列或冻结局部单元格

    Qt编程-QTableView冻结行或冻结列或冻结局部单元格 https://lcxing.blog.csdn.net/article/details/133745084 示例代码

    Qt 编程-地址薄开发

    通过学习Qt地址薄例子的编写过程,了解Qt开发的主要步骤和思想,掌握Qt开发的技巧

    Qt Quick核心编程

    Qt Quick核心编程-安晓辉著作.pdf Qt Quick核心编程-安晓辉著作.pdf Qt Quick核心编程-安晓辉著作.pdf Qt Quick核心编程-安晓辉著作.pdf Qt Quick核心编程-安晓辉著作.pdf Qt Quick核心编程-安晓辉著作.pdf Qt Quick...

    Qt4编程-源代码

    Qt4编程-源代码 Qt4编程-源代码 Qt4编程-源代码 Qt4编程-源代码

    Qt高级编程---------源码

    《Qt高级编程》,作者: (英)Mark Summerfield ,《qt高级编程》以工程实践为主旨,是对qt现有的700多个类和上百万字参考文档中部分关键技术深入、全面的讲解和探讨,如丰富的网络/桌面应用程序、多线程、富文本处理...

    qt-everywhere-src-5.12.12源码

    1、qt-everywhere-src-5.12.12的源代码 2、编者编译Qt5.12.12所使用的代码一并上传,方便大家下载编译.

    qt-vs-addin-1.2.4-opensource

    qt-vs-addin-1.2.4-opensourceQt,坦白来说,并不只是一个界面库,他是C++编程思想的集大成者。它是得到完善的C++应用程序框架。使用Qt,在一定程度上你获得的是一个“一站式”、“全方位”的解决方案,STL。string...

    精通Qt4编程--体系完整,内容实用

    《精通Qt4编程(第2版)》详细介绍了qt的基础知识和gui编程应用,举例翔实,内容全面,基本涵盖了qt编程的各个方面。全书共分3篇25章,包括qt gui编程的基础知识(对话框、基础窗口部件、程序主窗口、布局管理)、中级...

    优龙QT编程-快速入门

    优龙QT编程,分基础篇 入门篇 实战篇,让你对QT编程有一个大体的了解,方便快速入门。

    2-linux编程-驱动调用-QT编程.

    嵌入式的学习 linux编程-驱动调用-QT编程.

    《PYTHON QT GUI快速编程---PYQT编程指南》源码

    《PYTHON QT GUI快速编程---PYQT编程指南》,其英文原版书名为:《Rapid GUI Programming with Python and Qt》随书源码。

    《C++ GUI Qt 4 编程(第二版)》《C++ GUI programming with Qt4》高清-中文版-扫描版-PDF-part3

    《C++ GUI Qt 4 编程(第二版)》《C++ GUI programming with Qt4》高清-中文版-扫描版-PDF 分辨率在500dpi左右,清晰度,绝对高清有保证! 书签-封面-所有信息齐全。 绝对原版扫描,一页不漏! 由于文件大(清晰度...

    精通Qt4编程--精通Qt4编程

    基本涵盖了Qt编程的各个方面。全书共分3篇21章,包括Qt GUI编程的基础 知识(对话框、基础窗口部件、程序主窗口、布局管理),中级编程(2D绘图 、拖放操作与剪贴板、文件处理、网络编程、多线程、事件机制、数据库 ...

    QT5-STK二次开发实例

    2 QT编程 在QT项目中添加STK.h和STK.cpp(当然,你也可以改成其他名字,我这里就简单设置为STK.h和STK.cpp了),其中STK.h中包含CppIncludes目录中的AgStkUtil.tlh、AgVGT.tlh、AgStkObjects.tlh、STKX.tlh,注意需要...

    C++ GUI with Qt4编程 - 完整书签.pdf

    C++ GUI with Qt4编程 - 完整书签.pdf为学习Qt的经典之作,网上下载的pdf都没有标签或者标签不全。我自己整理了一下,现在为完整标签,包括每个小章节。

    QT图形编程--学习QT的好书

    本书向读者介绍利用Qt开发图形用户界面的应用程序的入门知识。这里,我们首先介绍了如何搭建Qt的开发环境,之后通过一些简单的示例程序来循序渐进地介绍Qt的“信号和槽”以及布局等基本概念。我们希望以此来...

    python QT GUI快速编程--pyqt编程指南

    python QT GUI快速编程--pyqt编程指南,快速学习pythonGUI开发,图形化编程。

Global site tag (gtag.js) - Google Analytics