The Event System(Qt的事件系统 )

英语没过四级,慎重参考偷笑

 

 

In Qt, events are objects, derived from the abstract QEvent class, that represent things that have happened either within an application or as a result of outside activity that the application needs to know about. Events can be received and handled by any instance of a QObject subclass, but they are especially relevant to widgets. This document describes how events are delivered and handled in a typical application.

 

在Qt中,事件是对象接收自抽象基类QEvent,它表示在一个应用程序内发生的或外部活动的结果这些事情。它需要被应用程序知道。事件可以被任意一个QObject的子类实例接收和处理,但与它最相关的是部件(QWidget)。本文介绍了如何在一个典型应用中传送和处理事件。

 

 

How Events are Delivered

When an event occurs, Qt creates an event object to represent it by constructing an instance of the appropriate QEvent subclass, and delivers it to a particular instance of QObject (or one of its subclasses) by calling its event()function.

This function does not handle the event itself; based on the type of event delivered, it calls an event handler for that specific type of event, and sends a response based on whether the event was accepted or ignored.

Some events, such as QMouseEvent and QKeyEvent, come from the window system; some, such as QTimerEvent, come from other sources; some come from the application itself.

事件是如何传递

当事件发生时,Qt创建一个事件对象(构建一个适当的QEvent子类的实例)来表示它,通过调用对象的event()函数传递事件到对象特定的实例。

这个函数并不能处理事件本身;根据传递的事件类型,它调用特定的事件类型的处理,并根据事件是被接受还是忽略做出响应。

一些事件,如QMouseEvent和QKeyEvent来自窗口系统;一些事件,如TimerEvent来自其他来源;一些事件来自应用程序本身。

 

 

 

 

Event Types

Most events types have special classes, notably QResizeEventQPaintEventQMouseEventQKeyEvent, and QCloseEvent. Each class subclasses QEvent and adds event-specific functions. For example, QResizeEvent adds size() and oldSize() to enable widgets to discover how their dimensions have been changed.

Some classes support more than one actual event type. QMouseEvent supports mouse button presses, double-clicks, moves, and other related operations.

Each event has an associated type, defined in QEvent::Type, and this can be used as a convenient source of run-time type information to quickly determine which subclass a given event object was constructed from.

Since programs need to react in varied and complex ways, Qt’s event delivery mechanisms are flexible. The documentation for QCoreApplication::notify() concisely tells the whole story; the Qt Quarterly article Another Look at Events rehashes it less concisely. Here we will explain enough for 95% of applications.

事件类型

大多数的事件类型有特定的类尤其是QResizeEvent,QPaintEvent,QMouseEvent,QEvent和CloseEvent。

每一个QEvent的子类都添加了事件特定的功能。例如QResizeEvent增加了size()和oldSize()让部件发现它们的尺寸是如何改变了。

一些类支持一个以上的事件类型。QMouseEvent支持鼠标按下、双击、移动和其他相关的操作。

每个事件具有一个相关类型,在QEvent::Type中定义。 这可以作为运行时类型信息可以快速确定给定的事件对象是从哪个子类构造的。

由于程序需要对复杂多变的方式作出反应,因此Qt的事件传递机制是灵活的。QCoreApplication::notify()文档简要说明了其原委;Qt季度文章Another Look at Events更加简洁的阐述了它。在这里我们所阐述的足够百分之95的应用程序使用。

 

 

Event Handlers

The normal way for an event to be delivered is by calling a virtual function. For example, QPaintEvent is delivered by calling QWidget::paintEvent(). This virtual function is responsible for reacting appropriately, normally by repainting the widget. If you do not perform all the necessary work in your implementation of the virtual function, you may need to call the base class’s implementation.

事件处理

去传递一个事件的通常方式是调用一个虚函数。例如,QPaintEvent通过调用QWidget::paintEvent()函数传递。该虚函数负责通过重绘部件恰当的,正确的做出反应。如果你在你的虚函数实现中不做必要的工作,你可能需要调用基类的实现。

 

 

For example, the following code handles left mouse button clicks on a custom checkbox widget while passing all other button clicks to the base QCheckBox class:

void MyCheckBox::mousePressEvent(QMouseEvent *event)

{

if (event->button() == Qt::LeftButton) {

// handle left mouse button here

} else {

// pass on other buttons to base class

QCheckBox::mousePressEvent(event);

}

}

 

例如,下面的代码处理了自定义复选框部件的鼠标左键点击事件,而其他所有按钮点击传递到基类QCheckBox中。

 

 

 

 

If you want to replace the base class’s function, you must implement everything yourself. However, if you only want to extend the base class’s functionality, then you implement what you want and call the base class to obtain the default behavior for any cases you do not want to handle.

 

如果你想更换基类的功能,你必须自己去实现一切。但是,如果你只想要扩展基类的功能,那么你实现你想要的并调用基类来获取默认行为(你不想去处理的事情)。

 

 

 

Occasionally, there isn’t such an event-specific function, or the event-specific function isn’t sufficient. The most common example involves Tab key presses. Normally, QWidget intercepts these to move the keyboard focus, but a few widgets need the Tab key for themselves.

 

有时候,存在没有事件特异性功能或特异性功能不充分的。最常见的例子包括按下Tab键,通常情况下,QWidget会拦截这些来移动键盘焦点。少数部件自己需要这些Tab事件。

 

 

 

These objects can reimplement QObject::event(), the general event handler, and either do their event handling before or after the usual handling, or they can replace the function completely. A very unusual widget that both interprets Tab and has an application-specific custom event might contain the following event() function:

 

这些对象可以重新实现QObject::event(),一般的事件处理,既可以在通常操作之前也可以在之后处理自己的事件,又或者可以完全取代这个函数。一个不寻常的部件,有两个解释选项卡,并具有特定应用程序的定制事件可能包含下面的event()函数:

bool MyWidget::event(QEvent *event)

{

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

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

if (ke->key() == Qt::Key_Tab) {

// special tab handling here

return true;

}

} else if (event->type() == MyCustomEventType) {

MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);

// custom event handling here

return true;

}

 

return QWidget::event(event);

}

 

 

 

Note that QWidget::event() is still called for all of the cases not handled, and that the return value indicates whether an event was dealt with; a true value prevents the event from being sent on to other objects.

注意QWidget::event()在所有情况不被处理时仍然被调用,那个返回值表示是否有事件被处理;返回true事件将不被发送到其他对象。

 

 

 

 

Event Filters

Sometimes an object needs to look at, and possibly intercept, the events that are delivered to another object. For example, dialogs commonly want to filter key presses for some widgets; for example, to modify Return-key handling.

事件过滤

有时候一个对象需要查看、拦截被传递到另一个对象的事件。例如,一般的对话要过滤一些部件的键盘按下;例如,去修改返回键处理。

 

 

 

The QObject::installEventFilter() function enables this by setting up an event filter, causing a nominated filter object to receive the events for a target object in its QObject::eventFilter() function. An event filter gets to process events before the target object does, allowing it to inspect and discard the events as required. An existing event filter can be removed using the QObject::removeEventFilter() function.

QObject::installEventFilter()函数通过设置事件过滤器可以实现这点,使任命的过滤对象接收这些事件(在它的eventFilter()函数里)。事件过滤器在目标对象之前得到事件处理,允许其检查,并根据需要丢弃事件。已经存在的事件过滤器可以通过QObject::removeEventsFilter()函数移除。

 

 

 

When the filter object’s eventFilter() implementation is called, it can accept or reject the event, and allow or deny further processing of the event. If all the event filters allow further processing of an event (by each returning false), the event is sent to the target object itself. If one of them stops processing (by returning true), the target and any later event filters do not get to see the event at all.

当过滤器对象的eventFilter()函数实现被调用,它可以接受或拒绝事件,允许或拒绝事件的进一步的处理。如果所有的过滤器允许事件进一步处理(每个都返回false),事件将会被发送到目标对象。如果他们中的一个停止处理(返回true),目标和后面的事件过滤器都不能看到事件。

 

bool FilterObject::eventFilter(QObject *object, QEvent *event)

{

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

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

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

// Special tab handling

return true;

} else

return false;

}

return false;

}

 

上面的代码演示了另一种方法截取发送到一个特定目标部件的的Tab按下事件。在这个例子中过滤器处理了相关的事件然后返回true阻止了他们进一步的处理。其他所有事件忽略,过滤器返回false允许他们被发送到目标部件,经过其他安装在目标部件上的事件过滤器。

 

 

 

It is also possible to filter all events for the entire application, by installing an event filter on the QApplication or QCoreApplication object. Such global event filters are called before the object-specific filters. This is very powerful, but it also slows down event delivery of every single event in the entire application; the other techniques discussed should generally be used instead.

另外,也可以为整个应用程序过滤所有的事件,通过在QApplication或QCoreApplication对象上安装事件过滤器。这种全局的事件过滤器在指定对象的过滤器之前调用。这是非常强大的,但它也减慢了整个应用程序的每一个事件的事件传递;其他被讨论的技术应当通常被用来代替使用(这句话不知道与上文有什么关系)。

 

Sending Events

Many applications want to create and send their own events. You can send events in exactly the same ways as Qt's own event loop by constructing suitable event objects and sending them with QCoreApplication::sendEvent() andQCoreApplication::postEvent().

发送事件

许多应用程序要创建并发送它们自己的事件。你可以发送事件如同Qt自己的事件循环完全一样的方式,通过构造一个合适的事件对象并用QCoreApplication::sendEvent()和QCoreApplication::postEvent()发送它们。

 

sendEvent() processes the event immediately. When it returns, the event filters and/or the object itself have already processed the event. For many event classes there is a function called isAccepted() that tells you whether the event was accepted or rejected by the last handler that was called.

sendEvent()会立即处理该事件。当它返回,事件过滤器和/或对象本身已经处理了事件。对于许多事件类有一个isAccepted()函数,告诉你事件是接受还是拒绝,通过最后一个被调用的处理者。

 

postEvent() posts the event on a queue for later dispatch. The next time Qt's main event loop runs, it dispatches all posted events, with some optimization. For example, if there are several resize events, they are compressed into one. The same applies to paint events: QWidget::update() calls postEvent(), which eliminates flickering and increases speed by avoiding multiple repaints.

postEvent()将事件抛到队列中稍后调度。下一次Qt主事件循环运行时,它会调度所有的事件,有做一些优化。例如:如果有几个resize事件,它们会被压缩成一个。这同样应用于paint事件:QWidget::update()调用postEvent(),消除了闪烁并避免了多个重绘增加了速度。

 

postEvent() is also used during object initialization, since the posted event will typically be dispatched very soon after the initialization of the object is complete. When implementing a widget, it is important to realise that events can be delivered very early in its lifetime so, in its constructor, be sure to initialize member variables early on, before there's any chance that it might receive an event.

postEvent()也用于对象的初始化中,因为在对象完成初始化后事件很快被调度。当在实现一个widget,意识到在它的生命周期早期时由可能接收到事件是很重要的,确保在任何有机会接收到事件之前初始化成员变量。

 

To create events of a custom type, you need to define an event number, which must be greater than QEvent::User, and you may need to subclass QEvent in order to pass specific information about your custom event. See the QEvent documentation for further details.

创建一个自定义类型的事件,你需要定义一个大于QEvent::User的事件编号,并子类化QEvent以传递你自定义事件需要的信息。更详细的资料参阅QEvent文档。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值