Reprint: http://www.qtcn.org/bbs/simple/?t31383.html
another look at Events (Talk again Events )
Recently in the study of QT event processing found a very good article, is a 2004 quarterly article, online has the translation of this article, but feel that part of the local translation is relatively rough, not very clear. Simply re-translated again, and quoted the original translation version of the paragraph. The following are used in their own way to understand the translation, because the level is limited, there are many deficiencies, I hope you correct.
another look at Events(again on events)
by Jasmin Blanchette
What are spontaneous events? Which event types can be passed or compressed together? Delivery (posting) and launch (sending) where is the difference between an event? When should I call accept () or ignore () in an event? If you don't know all the previous questions, then read on!
• The source of the event
• Manual Events
• Custom Event Types
• Accepted or ignored at the event?
the source of the event
Events can be divided into three types based on how they are generated and sent:
• The spontaneous event (spontaneous events) is generated by the windowing system. They are placed in a system queue and processed sequentially through the event loop
• The post event (posted events) is generated by the QT application. They are placed in the message queue for QT and are processed through the event loop.
• Launch events (sent events) are generated by the QT application, but they are sent directly to the target object.
When we call Qapplication::exec () at the end of the main () function, the application enters the Qt event loop. Conceptually, the event loop resembles the following:
while (!exit_was_called) {
while (!posted_event_queue_is_empty) {
Process_next_posted_event ();
}
while (!spontaneous_event_queue_is_empty) {
Process_next_spontaneous_event ();
}
while (!posted_event_queue_is_empty) {
Process_next_posted_event ();
}
}
First, the event loop handles all post events (posted events) until the event queue is empty. It then handles spontaneous events (spontaneous events) until all events are processed. Finally, it handles all the post events (posted events) that are generated during the process of spontaneous events (spontaneous event).
The launch event (sent events) is not handled by the event loop. They are passed directly to the object.
Let's take a look at how this works in the execution of the drawing events (paint events). When a widget is displayed for the first time, or when it is hidden and then becomes visible, the window System produces a (spontaneous) request to redraw the drawing event (Paint event) for that widget. Finally, the event loop gets the event and sends it to the widget that needs to be redrawn.
Not all drawing events (paint events) are generated by the windowing system. When you call Qwidget::update () to redraw a widget, the widget posts a drawing event (Paint event) to itself. The drawing event is queued and dispatched at the end by the event loop.
If you are impatient and don't want to wait for the event loop to redraw a widget, you can theoretically call PaintEvent () to force an immediate redraw. In practice, however, this is not necessarily possible because paintevent () is a protected function. This will also bypass any existing event filters. For this reason, QT provides a mechanism for direct emission (sending) events rather than post (posting) events. Qwidget::repaint () uses this mechanism to force an immediate redraw.
One advantage of the delivery event (posting events) over the launch (sending) event is that the delivery (posting) method gives Qt the opportunity to compress the event. If you call 10 update () consecutively on the same widget, and do not return an event loop, the 10 events generated by update () are automatically merged into a single event, and This process is accompanied by a merge of the regions specified in all of their qpaintevents objects.
Finally, it is important to note that you can call Qapplication::sendpostedevents () at any time to force QT to handle a post event for an object (posted events).
Manual events (that is, events that are actively fired by the application, not by the outside world)
QT applications can produce their own pre-defined or custom types of events. This is done by creating an object instance of Qevent (or its subclasses) and calling Qapplication::p ostevent () or qapplication::sendevent ().
Both of these functions have a qobject * and a qevent * type parameter. If you call Postevent (), then you must use the New keyword to create an event object, and when it is finished, QT will automatically delete it. If you call Sendevent (), then you must create the event object on the stack. Here is an example of a post (posting) event:
Qapplication::p ostevent (Mainwin, New Qkeyevent (qevent::keypress, key_x, ' X ', 0));
Here is an example of a launch (sending) event:
Qkeyevent event (qevent::keypress, key_x, ' X ', 0);
Qapplication::sendevent (Mainwin, &event);
QT applications rarely need to call postevent () or sendevent () directly, as most events are automatically generated by QT or windowing systems when needed. In most cases where you want to send an event, QT contains an advanced function to replace it (for example, Update () and repaint ()).
Custom Event Types
QT allows you to create your own event types. This technique is particularly useful in multithreaded applications and can be used as a means of communicating with GUI threads; see C + + GUI programming with Qt 3 (see page 359) for an example of chapter 17th.
Custom types are also useful in single-threaded applications and can be used as a communication mechanism between objects. The main reason you would prefer to use events instead of standard function calls or signals and slots is that events can be used synchronously or asynchronously (depending on whether you call Sendevent () or postevents ()), but calling a function or a slot is always synchronous. Another advantage of events is that they can be filtered. A more detailed discussion of this is in the following section.
Here's a snippet showing how to post a custom event:
Const Qevent::type MyEvent = (qevent::type) 1234;
...
Qapplication::p ostevent (obj, new qcustomevent (MyEvent));
The event must be of type qcustomevent (or a subclass). The argument to the constructor is the type of the event. Values below 1024 are reserved for pre-defined event types by QT, and others can be used by the application.
(Translator Note: In Qt4, custom events are created by subclasses of Qevent. Event-specific data is stored in the way that suits your application. Custom events are still sent to each object's Customevent () processor function, but they are treated as qevent objects instead of obsolete qcustomevent objects)
To handle custom event types, you need to overload the Customevent () function:
void Mylineedit::customevent (Qcustomevent *event)
{
if (event->type () = = MyEvent) {
MyEvent ();
} else {
Qlineedit::customevent (event);
}
}
Qcustomevent has a member of void * type that you can use for your own purposes. If you want more type safety, you can also subclass Qcustomevent and add other members. But then you also need to point the Qcustomevent object to your specific type in customevent ().
event handling and filtering
Events in QT can be processed at 5 different levels:
• Re-implement a specified event handler.
Qobject and Qwidget provide a number of special event handlers for different event types (for example, PaintEvent () for handling paint events).
• Heavy-duty qobject::event ().
The event () function is an entry point for all events of an object. The default implementation of the function in Qobject and Qwidget simply forwards the event to the specified event handler.
• Install an event filter in a Qobject object. An event filter is an object that can receive events before the events of another object reach the specified destination.
• Install an event filter in the Qapp. In particular, an event filter on a QAPP monitors all events that are sent to all objects in the application.
• Heavy-duty qapplication::notify (). The Qt event loop and sendevent () call the function to distribute the event. By overloading it, you can view the event before anyone else.
Some types of events can be spread by spreading. This means that if a target object does not handle an event, Qt tries to find another recipient for the event and calls Qapplication::notify () with the new target object.
For example, a key event is propagated, and if the widget that has the focus does not handle a keystroke event, Qt sends the same event to its parent widget, and then to the parent window widget, and so on, until the event reaches the topmost widget.
Accept or Ignore?
Events that can be propagated have an accept () and a ignore () function that you can call to tell the QT system that you "accept" or "ignore" the event. If an event handler calls accept () on an event, the event is not propagated, and if the event handler is called Ignore (), then QT will try to find another recipient.
If you are like most QT developers, you may never feel that calling accept () and ignore () in your program is a hassle. This is how QT is designed in a way that you typically do not need to call these functions. The default value is "accept", and the default execution of the event handler in Qwidget calls Ignore (). If you want to accept an event, then you just need to overload the event handler and avoid invoking the Qwidget event handler. If you want to ignore an event, simply pass it to the Qwidget event handler. The following code snippet illustrates this:
void Myfancywidget::keypressevent (Qkeyevent *event)
{
if (event->key () = = Key_escape) {
Doescape ();
} else {
Qwidget::keypressevent (event);
}
}
In this example, if the user presses the ESC key, we call Doescape () and the event is accepted (the default). The event is not propagated to the parent widget. If the user presses any other key, we call Qwidget's default event handler.
void Qwidget::keypressevent (Qkeyevent *event)
{
Event->ignore ();
}
Because ignore () is called, the event is propagated to the parent widget.
So far, we have assumed that Qwidget is the base class. However, by replacing Qwidget with other base classes, the same usage can be used at any level. For example:
void Myfancylineedit::keypressevent (Qkeyevent *event)
{
if (event->key () = = Key_sysreq) {
Dosystemrequest ();
} else {
Qlineedit::keypressevent (event);
}
}
If for some reason you use the event () function instead of a specific event handler (for example, Keypressevent ()) to handle events, the program is slightly different. The event () function returns a Boolean value that tells the caller whether an event is accepted or ignored (true means "accept"). It does not make sense to invoke the accept () or ignore () on an event in the events (). The "accept" token is a communication mechanism between a particular event handler and the events (), and the Boolean value returned by the event () is used for communication with qapplication::notify (). The execution of the default event () in Qwidget to convert the "accept" identity to a Boolean value is as follows:
BOOL Qwidget::event (qevent *event)
{
Switch (E->type ()) {
Case Qevent::keypress:
Keypressevent ((Qkeyevent *) event);
if (! ( (Qkeyevent *) event)->isaccepted ())
return false;
Break
Case Qevent::keyrelease:
Keyreleaseevent ((Qkeyevent *) event);
if (! ( (Qkeyevent *) event)->isaccepted ())
return false;
Break
...
}
return true;
}
What has been discussed so far not only applies to key events, but also to the mouse, scroll wheel, tablet, and context menu (the right-click menu) event.
The Shutdown event works differently. Calling Qcloseevent::ignore () cancels the close operation, but usually the accept () tells QT to continue with the close operation. To avoid any confusion, it is a good idea to explicitly call accept () or ignore () in your overloaded closeevent (), just like this:
void Mainwindow::closeevent (Qcloseevent *event)
{
if (Userreallywantstoquit ()) {
Event->accept ();
} else {
Event->ignore ();
}
}
Another look at events (again on events)