Qt事件研究

原创 2006年05月17日 01:31:00

Q
QEvent
QEvent类是所有事件类的基类。事件对象包含事件参数。
Qt的主事件循环(QApplication::exec())从事件队列取得本地窗口系统的事件,并将它们转变成QEvent,然后装转换好的事件发送给QObjects。
一般情况下,事件来自底层窗口系统,但是也有可能通过QApplication类的QApplication::sendEvent()和QApplication::postEvent()来手动发送事件。
QObject通过它自己的QObject::event()函数来接收事件。这个函数可以要其子数里重新实现以定义自己的事件处理和新增额外的事件类型。QWidget::event()就是一个典型的例子。默认情况下,事件像QObject::timerEvent()和QWidget::mouseMoveEvent()这样被分派给事件句柄(即事件处理函数)。QObject::installEventFilter()允许一个对像中途截取事件给另外的对象。
基本事件仅包含一个事件类型的参数,QEvent的子类包含附加参数可用来描述特殊的事件。


void QObject::installEventFilter ( const QObject * obj )
安装事件过滤器obj到这个对象。
一个对象上安装的事件过滤器对象能接收所有所有发送到这个对象的事件。(义 译)
Qt中有两种evenfilter,一种是一般的对象的eventfilter一种是application的eventfileter。

QPEApplication::eventFilter和鼠标左键长按变为右键、输入法、contextmenu等有关。
(过滤器对象可以是安装过滤器的对象本身,也可以是其它对象,但不管怎样,过滤器对象都是通过eventFilter()函数来进行事件的过滤操作的,是不是这样的?当然,如果过滤器对象是自己本身的话,也就没有什么意义了)
事件过滤器就是接收所有被发送到这个对象的事件的对象。这个过滤器可以停止事件或者把它再转给这个对象。事件过滤器obj通过它的eventFilter()函数来接收事件。如果事件被过滤了(比如,停止了),eventFilter()函数必须返回真,否则它必须返回假。

如果有多个事件过滤器被安装到同一个对象上,最后一个被安装的事件过滤器将先被激活。

实例:

    #include <qwidget.h>

    class MyWidget : public QWidget
    {
        Q_OBJECT
    public:
        MyWidget( QWidget *parent = 0, const char *name = 0 );

    protected:
        bool eventFilter( QObject *, QEvent * );
    };

    MyWidget::MyWidget( QWidget *parent, const char *name )
        : QWidget( parent, name )
    {
        // 为父对象(如果有的话)安装一个过滤器
        if ( parent )
            parent->installEventFilter( this );
    }

    bool MyWidget::eventFilter( QObject *o, QEvent *e )
    {
        if ( e->type() == QEvent::KeyPress ) {
            // 对于键被按下进行特殊处理
            QKeyEvent *k = (QKeyEvent *)e;
            qDebug( "Ate key press %d", k->key() );
            return TRUE; // 吃掉了这个事件
        } else {
            // 标准事件处理
            return QWidget::eventFilter( o, e );
        }
    }
   
例如,QAccel类使用这种技术来截取快捷键被按下。

警告:如果在你的eventFilter()函数中你删除了接收对象,请确认返回真。否则,Qt会把这个事件转给被删除的对象并且程序也许会崩溃。


bool QObject::eventFilter ( QObject * watched, QEvent * e ) [虚函数]
如果这个对象已经被安装为watched对象的一个事件过滤器,就过滤事件。
在这个函数你的重新实现中,如果你想过滤出e事件,比如,停止它的进一步处理,返回真,否则返回假。

警告:如果你在这个函数中删除接收对象,请确认返回真。否则,Qt会把这个事件转给被删除的对象并且程序也许会崩溃。


也可以参考installEventFilter()。

在QAccel、QScrollView和QSpinBox中被重新实现。


eventFilter被执行的代码
/*!
  /internal
  Activates all event filters for this object.
  This function is normally called from QObject::event() or QWidget::event().
*/

bool QObject::activate_filters( QEvent *e )
{
    if ( !eventFilters )   // no event filter
 return FALSE;
    QObjectListIt it( *eventFilters );
    register QObject *obj = it.current();
    while ( obj ) {    // send to all filters
 ++it;     //   until one returns TRUE
 if ( obj->eventFilter(this,e) ) {
     return TRUE;
 }
 obj = it.current();
    }
    return FALSE;    // don't do anything with it
}


signal与event
emit的是一个signal,不是一个event,signal本质上是一个callback,是synchronous;
所谓的event一般是通过postEvents()是会进入进程主循环的queue中的,是asynchronous,但是event也可sendEvent()(这种用法是synchronous)
signal的发出者是对象;event的发出者一般来说是窗口系统。
Signals are useful when using a widget, whereas events are useful when implementing a widget. 即在实现一个组件的时候用事件,
例如QButton里
void clicked()是一个信号,它通过keyPressEvent与keyReleaseEvent()来实现。


responsive stay机制
1 当对于要处理一个会消耗时间的事件的时候,如果不做任何处理的话,下面的事件就会马上处理,表现为暂时的假死机。
2 有两种方式可以解决这个问题。之一是use multiple threads在另外一个thread中处理消耗事件的工作。
3 另外一种简单的替代的方式是responsive stay 也就是那些消耗事件的代码一般都是一个循环,在每执行一次的时候调用:qApp->processEvents();
在C++ GUI Programming with Qt 3.chm有一个写文件的例子
for (int row = 0; row < NumRows; ++row) {
        for (int col = 0; col < NumCols; ++col) {
            QString str = formula(row, col);
            if (!str.isEmpty())
                out << (Q_UINT16)row << (Q_UINT16)col << str;
        }
        qApp->processEvents();
    }
 

详细见这个书上的内容
Qtopia2.10中也有用的地方。比如:sysinfor清除一些文件的时候。
(在开机动画中也有一个特殊的用法,这时候app的主循环还没有进入,不过这不属于responsive stay)

Qt中事件处理的方法和实例

一、Qt中事件处理的方式   1、事件处理模式一         首先是事件源产生事件,最后是事件处理器对这些事件进行处理。然而也许大家会问, Qt中有这么多类的事件,我们怎么...
  • lpmygod
  • lpmygod
  • 2014年09月08日 11:45
  • 12260

qt 双击事件处理

qt双击事件响应和实现       接着上面的播放器全屏功能来写,一般播放器的全屏都是通过双击左键来实现的。 qt中有一个事件叫做mouseDoubleClickEvent,对应的就会有一...
  • sduvec
  • sduvec
  • 2014年06月04日 20:51
  • 8292

Qt学习之路(20): 事件接收与忽略

Qt学习之路(20): 事件接收与忽略 2009-11-11 22:32:23 标签:C++ 教程 学习 QT教程 Qt 原创作品,允许转载,转载时请务必以超链接形式标明文章 原...
  • carrie0728
  • carrie0728
  • 2016年07月06日 13:34
  • 635

QT中的event事件解析

在QT中使用一个对象表示一个事件,继承自QEvent类。需要说明的是事件与信号是不相同的。在每个程序的main()函数的最开始都会调用QApplication类的exec()函数,它会使Qt应用程序进...
  • qq_21792169
  • qq_21792169
  • 2016年11月25日 21:39
  • 2933

Qt事件总结(鼠标、键盘)

Qt 程序需要在main()函数创建一个QCoreApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行 exec()函数之后,程序将进入事件循环来监听应...
  • lovebird_27
  • lovebird_27
  • 2015年12月18日 13:52
  • 11958

python3+PyQt5 重新实现QT事件处理程序

本文是对《Python Qt GUI快速编程》的第10章的例子events用Python3+PyQt5进行改写,涉及到重新实现QWidget的事件处理程序。可作为重新实现事件处理程序的参考。...
  • xiaoyangyang20
  • xiaoyangyang20
  • 2017年01月24日 11:21
  • 483

Qt学习之路之鼠标事件

鼠标事件包括移动,鼠标按下,释放(松开),单击,双击....... 要自定义鼠标事件,需重写虚函数: void QWidget::mousePressEvent(QMouseEvent * even...
  • HK_5788
  • HK_5788
  • 2015年01月08日 20:38
  • 12376

移动端 jquery 长按触发移动事件 <升级版>

长按触发移动事件,可以用于手机界面上返回导航图标 等等 将代码拷贝到本地,进行测试 在手机端测试,或者通过谷歌浏览器F12 测试 增加了对长按时间的判断,区分单击事件和长...
  • shipeng22022
  • shipeng22022
  • 2015年11月30日 13:54
  • 11331

ExpandableListView为child子列表添加长按事件(有部分内容是网上内容,但大部分是我自己的理解)

ExpandableListView设置子列表长按事件最好用简单的方法,网上找的用一些方法很多都有意外,这个没有!!...
  • gxp1182893781
  • gxp1182893781
  • 2016年11月12日 21:51
  • 1140

从零开始学android:Android事件处理—长按事件

长按事件 在Android中提供了长按事件的处理操作,所谓的长按事件就好象读者经常使用某一个手机,长按某一个组件2秒之后才会触发这一操作,而不像普通的单击事件那样,每次单击都会执行一次,长按事件使用V...
  • e421083458
  • e421083458
  • 2013年12月07日 21:05
  • 34363
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Qt事件研究
举报原因:
原因补充:

(最多只允许输入30个字)