Events are the core concept of GUI applications. GUI applications perform their functions by executing events. The event loops, event distribution, and event interceptions designed around events are all
Gui
The core part of the framework and the basis for running it are links to all other objects. In QT, the event loop and event mechanism are encapsulated in qeventloop. This article briefly introduces
Let's take a look at the event Running Mechanism in QT.
1. Event Classification
Events in QT mainly include the following types:
(1) qwsevent and qwscommand
This is the event used for qwsclient and qwsserver communications. qws
The client sends a qwscommand request to the qws server, and the qws server returns the qwsevent response to the qws client.
Qwsevent and qwscommand are the socket events used by the client to communicate with the server.
The qwsevent event is saved in qptrlist <qwsevent> queue of qapplication: data.
Qwscommand is stored in qptrlist <qwscommandstruct> commandqueue of qwsserver;
(2) qevent
Qevent is in qws
Events used by each qobject in the client. It encapsulates various window messages, such as qshowevent, qfocusevent, and qmoveevent.
Qevent is mainly sent using sendevent and postevent. sendevent is a synchronous message, which is called synchronously without going through the event loop. It is not saved and directly
Call qobject: event (). Postevent is an asynchronous call. First place the event in the globalpostedevents queue
In qeventloop: processevents, globalpostedevents is checked cyclically.
(3) qsocket events
A qsocket event is a qevent of the type qevent: sockact, but its processing method is different from a general qevent.
The qsocket event can be used to handle process communication. The qwsevent/qwscommand event is passed through qsocket.
Qeventloop management.
(4) qtimer event
Like qsocket events, qtimer is a qevent of the qevent type: timer, but its processing method is different from the general qevent.
The qtimer event is placed on the global object: static timerlist * timerlist.
2. qsocket and qeventloop
Qsocket is bound with a socket FD, and each socket
FD can have three actions: read, write, and exception. Each action is encapsulated by a qsocketnotifier.
Qsocketnotifies is registered to qeventloop through qeventloop: registersocketnotifier.
Qeventloop: unregistersocketnotifier.
Qeventloop uses qsocknot to encapsulate a qsocketnotifier and the corresponding operation type.
In qsocknottype, The select_fds queue for the same operation is created and used directly for select.
Qeventloop stores three types of qsocknottypes based on the three operations (read/write/exceptions) of socket FD.
3. qeventloop: processevents
Qeventloop: processevents is an event loop call to check whether events are lined up by events.
Qapplication: exec/qeventloop: enterloop is called cyclically.
Qeventloop: processevents.
The following describes the implementation of qeventloop: processevents to describe the event distribution process.
Bool
Qeventloop: processevents (processeventsflags flags)
{
//
Process events from the qws Server
Int nevents = 0;
......
// Handle GUI and posted events
If (qt_is_gui_used ){
//.
First, execute the events in the globalpostedevents queue. All these events are performed through the qapplication: postevent or
Qthread: sent by postevent
Qapplication: sendpostedevents ();
// B.
Check qwsevent queue: qapplication: qptrlist of Data <qwsevent> queue
While
(Qt_fbdpy-> eventpending () {// also flushes output buffer
If (D-> else cut ){
Return false;
}
Qwsevent * event = qt_fbdpy-> getevent (); // get next event
Nevents ++;
Bool ret = qapp-> qwsprocessevent (event) =
1;
Delete event;
If (RET ){
Return true;
}
}
}
If (D-> else cut ){
Return false;
}
// C.
For qwsserver, check qptrlist of qwsserver <qwscommandstruct>
Commandqueue queue.
Extern qptrqueue <qwscommand>
* Qt_get_server_queue ();
If (! Qt_get_server_queue ()-> isempty ()
){
Qwsserver: processeventqueue ();
}
// D. If the preceding event has been executed
Generate postedevent in the process and execute it again. The main requirement is moveevent, resizeevent, and paintevent.
Qapplication: sendpostedevents ();
// Don't block if
Exitloop () or exit ()/quit () has been called.
Bool canwait =
D-> exitloop | D-> quitnow? False: (flags & waitformore );
// Process timers and socket notifiers-the Common Unix stuff
// E.
Check the minimum sending time in the timer event queue and the select wait time.
// Return the maximum time
We can wait for an event.
Static timeval zerotm;
Timeval
* TM = qt_wait_timer (); // wait for timer or event
If (! Canwait)
{
If (! TM)
TM = & zerotm;
TM-> TV _sec = 0 ;//
No time to wait
TM-> TV _usec = 0;
}
// F. Prepare the Select call
Required FD queue.
Int highest = 0;
If (! (Flags &
Excludesocketnotifiers )){
// Return the highest FD we can wait
For input on
If (D-> sn_highest> = 0 ){
// Has socket Notifier (s)
If (D-> sn_vec [0]. List &&!
D-> sn_vec [0]. List-> isempty ())
D-> sn_vec [0]. select_fds =
D-> sn_vec [0]. enabled_fds;
Else
Fd_zero (
& D-> sn_vec [0]. select_fds );
If (D-> sn_vec [1]. List
&&! D-> sn_vec [1]. List-> isempty ())
D-> sn_vec [1]. select_fds = D-> sn_vec [1]. enabled_fds;
Else
Fd_zero (& D-> sn_vec [1]. select_fds );
If (
D-> sn_vec [2]. List &&! D-> sn_vec [2]. List-> isempty ())
D-> sn_vec [2]. select_fds = D-> sn_vec [2]. enabled_fds;
Else
Fd_zero (& D-> sn_vec [2]. select_fds );
}
// G. Check whether
Registered preselect_handler
If (qt_preselect_handler ){
Qvfunclist: iterator
It, end = qt_preselect_handler-> end ();
For (IT =
Qt_preselect_handler-> begin (); it! = End; ++ it)
(** It )();
}
// H. Execute the Select call.
...................
NSEL = select (
Highest + 1,
& D-> sn_vec [0]. select_fds,
& D-> sn_vec [1]. select_fds,
& D-> sn_vec [2]. select_fds,
TM );
...............
// I.
Check whether there is a wake-up message sent by the thread.
// Some other thread woke us up... consume
Data on the thread pipe so that
// Select doesn' t immediately
Return next time
If (NSEL> 0 & fd_isset (
D-> thread_pipe [0], & D-> sn_vec [0]. select_fds )){
Char C;
: Read (
D-> thread_pipe [0], & C, 1 );
}
// J. check whether a registered
Postselect_hander event
If (qt_postselect_handler ){
Qvfunclist: iterator
It, end = qt_postselect_handler-> end ();
For (IT =
Qt_postselect_handler-> begin (); it! = End; ++ it)
(** It )();
}
// K. Check all socket FD that can be operated and execute the corresponding qsocketnotifier: Activated ()
// Activate socket notifiers
.....................
Nevents + =
Activatesocketnotifiers ();
// L. Check whether the timerlist has a timeout timer and execute it.
// Activate timers
Nevents + = activatetimers ();
//
Return true if we handled events, false otherwise
Return (nevents
> 0 );
}
4. Event Interception
In addition to event queues, event loops, and event distribution, event interception is also an important function. Some objects need
If you know whether other objects are in the same event type and can intercept an event, you need to add a filter, which is called a hook in Win32. Qt
The filters supported in embeded are limited. Only qwsevent and qevent messages of the same process can be intercepted.
(1) Interception of qwsevent
Qwsevent
It is troublesome to intercept, only by reloading qapplication: qwseventfilter.
Qapplication: qwsprocessevent first calls
Qapplication: qwseventfilter to determine whether to process this qwsevent. Therefore
Qapplication: qwseventfilter is the best chance to intercept qwsevent.
(2) qevent Interception
This
It is quite simple, and is supported by QT native. A filter is installed through qobject: installeventfilter.
Qevent event execution is
Distributed by qobject: event. Qobject: when the event is executed, the system checks whether a filter has been installed. If yes, the system executes
Eventfilter function. Therefore, you only need to override this eventfilter function to implement the filter function.