1.事件的来源 来源于 a)windows系统的事件,经Qt的包装(如QMouseEvent); b)Qt内置的事件(如QTimerEvent); c)应用程序自定义的事件 2.处理事件的位置 2.1 重载虚拟方法 比如一个按钮,要自定义左键click时的行为,可以这样做: a. 从一个QPushButton上派生一个子类如MyPushButton b. 重载void MyPushButton::mousePressEvent(QMouseEvent *event) * 一般来讲,除非要重新改写这个事件的默认行为,否则如果仅是为了扩展其功能,最好在函数的最后call默认的父类处理方法,如QPushButton::mousePressEvent(event); * 在调用mousePressEvent这些特定的事件前,先调用通用事件处理函数,QObject::event()。因此,对于一些特殊情况,我们必须要重定义event(),如我们要对tab键进行重定义。默认的tab键是将focus移到下一个widget上去。比如在一个text edit widget里,我们可能希望tab键是向右形成一个置表位置,这时需要在text edit widget的event()进行处理。
2.2 event filter(事件过滤器)方法 一个对象的event filter的处理优先级在 该对象的 event()方法调用之前。这时,filter对象的eventFilter()方法被调用 * 使用QCoreApplication的事件过滤,可以将任何事件在进行具体对象之前,进行处理。但需要注意,这可能会使得整个事件处理过程变慢。 - Reimplementing QCoreApplication::notify. This is very powerful, providing complete control; but only one subclass can be active at a time.
- Installing an event filter on QCoreApplication::instance(). Such an event filter is able to process all events for all widgets, so it's just as powerful as reimplementing notify(); furthermore, it's possible to have more than one application-global event filter. Global event filters even see mouse events for disabled widgets.
- Reimplementing QObject::event() (as QWidget does). If you do this you get Tab key presses, and you get to see the events before any widget-specific event filters.
- Installing an event filter on the object. Such an event filter gets all the events except Tab and Shift-Tab key presses.
- Reimplementing paintEvent(), mousePressEvent() and so on. This is the commonest, easiest and least powerful way.
3. 自定义事件 3.1 自定义事件从QEvent派出,该event number必须大于QEvent::User 3.2 使用postEvent和sendEvent方法派遣自定义事件 * postEvent实质是将事件推进事件循环(event loop),马上返回。事件的实际发送可能在稍后的一个事件处理时钟内。 * 在某种意义上,程序可以直接调用对象的对应事件函数,而绕过postEvent。但存在不足, a)很多事件处理函数是protected,意味着你不能直接调用; b)这种直接调用将绕过event filter;Qt的解决方法是sendEvent。比如repaint()实质是调用了sendEvent。 * sendEvent等待事件被发送成功或失败后才返回。 * postEvent的一个好处是多个posted的event可以被压缩成单一的event,从而提高了效率。 * 可以使用QCoreApplication::sendPostedEvents强迫Qt马上进入事件循环(event loop)派遣事件。 4. 事件的传播(propogation) 如果事件在目标对象上得不到处理,事件向上一层进行传播,直到最顶层的widget为止。 如果得到事件的对象,调用了accept(),则事件停止继续传播;如果调用了ignore(),事件向上一级继续传播。 Qt对自定义事件处理函数的默认返回值是accept(),但默认的事件处理函数是ingore()。因此,如果要继续向上传播,调用QWidget的默认处理函数即可。到时为止的话,不必显式调用accept()。 但在event处理函数里,返回true表示accept,返回false表示向上级传播。 * 在closeEvent是个特殊情形,accept表示quit,ignore表示取消,所以最好在closeEvent显式调用accept和ignore。 5. tips 5.1 使用event->type得到事件的具体类型,对之进行判断,是否是需要的类型(比如KeyPress),然后进行相应处理 5.2 使用static_cast<specific event type *>对通用事件转换成特定类型,比如将event转成QKeyEvent *,然后调用QKeyEvent::key()取得按下什么键。 5.3 使用sendEvent时,参数 event,必须是局部变量,因为sendEvent不负责对event的删除。而postEvent的event参数,则必须是 new分配的heap对象,post完了后会自动删除。
|