Learning QT
Qt event mechanism:
Event origin:
Based on how events are generated and distributed, events can be divided into three types:
* Taneous events are generated by the window system. They are placed in the system queue and processed one by one through an event loop.
* Posted event, which consists of QT or application Program Generated, which is formed by QT and then processed through the event loop.
* Sent events are generated by QT or applications, but they are directly sent to the target object.
When we call qapplication: exec () at the end of the main () function, the program enters the QT event loop. In general, the event loop is shown below:
While (! Exit_was_called)
{
While (! Posted_event_queue_is_empty)
{
Process_next_posted_event ();
}
While (! Spontaneous_event_queue_is_empty)
{
Process_next_inclutaneous_event ();
}
While (! Posted_event_queue_is_empty)
{
Process_next_posted_event ();
}
}
First, the event cyclically processes all posted events until the queue is empty. Then it processes all the spontaneous events, and finally it processes all the posted events generated by processing the Spontaneous event. Send events are not processed in the event loop, and they are directly sent to the target object. Now let's take a look at how the paint event works. When a widget is visible for the first time or after being blocked, it becomes visible again,
The window system generates a (repeated taneous) paint event, requiring the program to redraw the widget. The event loop finally selects the event from the event queue and distributes it to the widget that needs to be repainted.
Not all painting events are generated by the window system. When you call qwidget: Update () to forcibly redraw the widget, the widget will post a painting event to itself. This paint event is put into the queue and finally distributed cyclically by the event.
If you are impatient and cannot wait for the event loop to re-draw a widget, theoretically, you should directly call paintevent () to force immediate re-painting. But in fact this is not always feasible, because the paintevent () function is protected (probably cannot be accessed ). It bypasses any existing event filters. For these reasons, QT provides a mechanism to directly sending events instead of posting.
Qwidget: repaint () uses this mechanism to force immediate re-painting.
One advantage of posting over sending is that it gives QT a chance to compress events. If you call Update () ten times consecutively on a widget, the ten events generated by Update () will be automatically merged into a separate event, however, the region information attached to the qpaintevents event is also merged. The following event types can be compressed: paint, move, resize, layout hint, and language change.
Finally, you can call qapplication: sendpostedevent () at any time to force QT to generate an object posted event.
Artificial events
Qt applications can generate their own events, predefined types, or custom types. You can create a qevent class or its
And call qapplication: postevent () or qapplication: sendevent.
These two functions require a qobject * and A qevent * as parameters. If you call postevent (), you must use the new operator to create an event object, qt will help you delete it after it is processed. If you use sendevent (), you should create events on the stack. The following are two examples:
First, the posting event:
Qapplication: postevent (mainwin, new qkeyevent (qevent: keypress, key_x, 'x', 0 ));
Second, the sending event:
Qkeyevent event (qevent: keypress, key_x, 'x', 0 );
Qapplication: sendevent (mainwin, & event );
Qt applications seldom directly call postevent () or sendevnet () because most events are automatically generated by QT or the window system when necessary.
. In most cases, when you want to send an event, QT has prepared a more advanced function to serve you. (For example
Update () and repaint ()).
Custom Event types
Qt allows you to create your own event types, which is particularly useful in multithreaded programs. In a single-threaded program, it can also be used
A communication mechanism between objects. The main reason why you should use events instead of other standard function calls, or signals and slots is that events can be used both for synchronization and Asynchronization (depending on your calls to sendevent () or posteven TS (), function calls or slot calls are always synchronized. Another benefit of an event is that it can be filtered.
Demonstrate how to post a Custom Event Code Fragment:
Const qevent: Type myevent = (qevent: type) 1234;
...
Qapplication: postevent (OBJ, new qcustomevent (myevent ));
The event must be of the qcustomevent type (or subclass. The constructor parameters are of the event type and are retained by QT below 1024. Other applications can be used. To process Custom Event types, you must re-implement the customevent () function:
Void mylineedit: customevent (qcustomevent * event)
{
If (Event-> type () = myevent ){
Myevent ();
} Else {
Qlineedit: customevent (event );
}
}
The qcustomevent class has a void * member for specific purposes. You can also subclass qcustomevent and add other members, but you also need to convert qcustomeevent to your specific type in customevent.
Event Processing and filtering
Events in QT can be processed at five different levels.
1. Implement a specific event handler again.
Qobject and qwidget provide many special event handlers, which correspond to different event types respectively. (For example, paintevent () corresponds to the paint event)
2. Implement qobject: event () again ()
The event () function is the entry to all object events. The default Implementation of qobject and qwidget is to simply push events into specific event handlers.
3. Install the Event Filter on qobject.
An event filter is an object that receives events from other objects until these events reach the specified target.
4. install an Event Filter on AAPP, which monitors all events sent to all objects in the program.
5. Re-implement qapplication: Notify (), QT event loop and sendevent () to call this function to distribute events. By Rewriting it, you can see events before others.
Some event types can be passed. This means that if the target object does not process an event, QT will try to find another event receiver. Call qapplication: Y () with the new target (). For example, key events are transmitted. If a widget with focus does not process a specific key, QT will distribute the same event to the parent widget, and then the parent's father until the top widget.
Accept or ignore?
The events that can be passed have an accept () function and an ignore () function. You can use them to tell QT that you "receive" or
"Ignore" this event. If the event handler calls accept (), the event will not be passed. Assume that the event handler calls
Ignore (), QT will try to find another event receiver.
Like most developers, you may not be troubled by calling accept () or ignore. The default value is "receive ".
The default implementation in qwidget is to call ignore (). If you want to receive events, you need to re-implement the event handler to avoid
Call the implementation of qwidget. If you want to "Ignore" the event, simply pass it to the implementation of qwidget. The following code demonstrates this:
Void myfancywidget: keypressevent (qkeyevent * event)
{
If (Event-> key () = key_escape ){
Doescape ();
} Else {
Qwidget: keypressevent (event );
}
}
In the above example, if the user presses the "ESC" key, we will call doescape () and the event is "received" (this is the default situation ),
Events are not passed to the parent widget. If you press another key, the default Implementation of qwidget is called.
Void qwidget: keypressevent (qkeyevent * event)
{
Event-> ignore ();
}
Thanks to ignore (), the event will be passed to the parent widget.
So far, we have assumed that the base class is qwidget. However, the same rule can be applied to other layers as long as qwidget is used.
Replace the base class. For example:
Void myfancylineedit: keypressevent (qkeyevent * event)
{
If (Event-> key () = key_sysreq ){
Dosystemrequest ();
} Else {
Qlineedit: keypressevent (event );
}
}
For some reason, you will process events in event () instead of in a specific handler, such as keypressevent (). This process may be somewhat different. Event () returns a Boolean value to tell the caller whether the event is accept or ignore. (true indicates accept), and CALLS accept () or ignore () from event () is meaningless. The "accept" mark is a communication mechanism between the event () and the handler of a specific event. The Boolean value returned from event () is used to communicate with qapplication: Y. In qwidgetk, the default event () implementation is to convert "accept" and mark it as a Boolean value, as shown below:
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;
}
Till now, the content we mentioned is not only applicable to key events, but also for mouse, wheel, tablet, context menu, and other events.
The close event is a bit different. Calling qcloseevent: Ignore () cancels the close operation, while accept () tells QT to continue the normal close operation. To avoid confusion, it is best to explicitly call accept () and ignore () in the new implementation of closeevent:
Void mainwindow: closeevent (qcloseevent * event)
{
If (userreallywantstoquit ()){
Event-> Accept ();
} Else {
Event-> ignore ();
}
} VV