Qt source code parsing (4) Analysis of QT event mechanism principles

Source: Internet
Author: User

Copyright Notice

Respect Original Works. Reprinted, please maintain the integrity of the article, and in the form of a hyperlink to indicate the original author "tingsking18" and the main site address, so that other friends can ask and correct.

 

 

Qt source code parsing (1) Qt creates window programs, message loops, and winmain Functions

Qt source code analysis (2) in-depth analysis of QT Object System and signal Slot Mechanism

Qt source code analysis (3) in-depth analysis of QT Object System and signal slot mechanism (continued)

Qt source code parsing (4) Analysis of QT event mechanism principles

Qt source code parsing (5) Implementation of cross-platform calling of dynamic libraries in qlibrary

Qt source code parsing (6) connection between QT signal slot mechanism and event mechanism

Qt source code parsing (7) process of creating a form using QT

Qt source code parsing (8) How QT processes Windows messages

Qt source code parsing (9) parsing qdatetime

 

App.exe C () is the last word in mainpipeline when you use qtto write GUI programs. Many books explain this sentence as a message loop by bringing the QT program into the message loop. Next we will go to the exec () function and look at its implementation principles.
Let's go!
First, go to qtdir/src/corelib/kernel/qcoreapplication. cpp

Int qcoreapplication: exec ()
{
If (! Qcoreapplicationprivate: checkinstance ("EXEC "))
Return-1;
// Obtain thread data
Qthreaddata * threaddata = self-> d_func ()-> threaddata;
// Determine whether the master thread is created
If (threaddata! = Qthreaddata: Current ()){
Qwarning ("% s: Exec: Must be called from the main thread", self-> metaobject ()-> classname ());
Return-1;
}
// Determine whether eventloop has been created
If (! Threaddata-> eventloops. isempty ()){
Qwarning ("qcoreapplication: Exec: The Event loop is already running ");
Return-1;
}

Threaddata-> quitnow = false;
Qeventloop eventloop;
Self-> d_func ()-> in_exec = true;
// Create eventloop
Int returncode = eventloop.exe C ();
Threaddata-> quitnow = false;
If (Self ){
Self-> d_func ()-> in_exec = false;
// Exit the program
Emit self-> abouttoquit ();
Sendpostedevents (0, qevent: deferreddelete );
}
Return returncode;
}
Then go to qeventloop. cpp.
Int qeventloop: exec (processeventsflags flags)
{
Q_d (qeventloop );
If (D-> threaddata-> quitnow)
Return-1;
// Exec has been called.
If (D-> inexec ){
Qwarning ("qeventloop: Exec: instance % P has already called exec ()", this );
Return-1;
}
D-> inexec = true;
D-> exit = false;
+ D-> threaddata-> looplevel;
// Push event-class objects into the thread struct
D-> threaddata-> eventloops. Push (this );

// Remove posted quit events when entering a new event Loop
// This sentence does not need to be translated!
If (qapp-> thread () = thread ())
Qcoreapplication: removepostedevents (qapp, qevent: Quit );

# If defined (qt_no_exceptions)
While (! D-> Exit)
// This is the key. We need to keep tracking.
Processevents (flags | waitformoreevents );
# Else
Try {
While (! D-> Exit)
Processevents (flags | waitformoreevents );
} Catch (...){
// If exception is used, the next time is processed.
Qwarning ("QT has caught an exception thrown from an event handler. Throwing/N"
"Exceptions from an event handler is not supported in QT. You must/N"
"Reimplement qapplication: Policy () and catch all exceptions there./N ");
Throw;
}
# Endif
// Extract the time object from the thread structure before exiting eventloop.
Qeventloop * eventloop = D-> threaddata-> eventloops. Pop ();
Q_assert_x (eventloop = This, "qeventloop: exec ()", "internal error ");
Q_unused (eventloop); // -- release warning

D-> inexec = false;
-- D-> threaddata-> looplevel;
// Exit the event loop.
Return D-> returncode;
}

Came to the processevents function:
Bool qeventloop: processevents (processeventsflags flags)
{
Q_d (qeventloop );
// Determine whether the event dispatcher is empty.
If (! D-> threaddata-> eventdispatcher)
Return false;
If (flags & deferreddeletion)
Qcoreapplication: sendpostedevents (0, qevent: deferreddelete );
// Call the event dispatcher on different platforms to process events.
Return D-> threaddata-> eventdispatcher-> processevents (flags );
}

Processevents is a pure virtual method defined in the qiniacteventdispatcher class. The qeventdispatcherwin32 class has the implementation of processevents.

Bool qeventdispatcherwin32: processevents (qeventloop: processeventsflags flags)
{
Q_d (qeventdispatcherwin32 );
// Create internal data. Registerclass registers the window class, And createwindow creates a form.
// Register socket notifiers and start all normal timers
If (! D-> internalhwnd)
Createinternalhwnd ();

D-> interrupt = false;
Emit awake ();

Bool canwait;
Bool retval = false;
Do {
Qcoreapplicationprivate: sendpostedevents (0, 0, D-> threaddata );

DWORD waitret = 0;
Handle phandles [maximum_wait_objects-1];
Qvarlengtharray <MSG> processedtimers;
While (! D-> interrupt ){
DWORD ncount = D-> wineventnotifierlist. Count ();
Q_assert (ncount <maximum_wait_objects-1 );

MSG;
Bool havemessage;

If (! (Flags & qeventloop: excludeuserinputevents )&&! D-> queueduserinputevents. isempty ()){
// Process queued user input events processes user input events and puts them in the queue.
Havemessage = true;
MSG = D-> queueduserinputevents. takefirst ();
} Else if (! (Flags & qeventloop: excludesocketnotifiers )&&! D-> queuedsocketevents. isempty ()){
// Process queued socket events processes socket events and puts them in the queue.
Havemessage = true;
MSG = D-> queuedsocketevents. takefirst ();
} Else {
// Retrieve the message from the message queue, which is the same as the peekmessage
Havemessage = winpeekmessage (& MSG, 0, 0, 0, pm_remove );
If (havemessage & (flags & qeventloop: excludeuserinputevents)
& (Msg. Message> = wm_keyfirst
& MSG. Message <= wm_keylast)
| (Msg. Message> = wm_mousefirst
& MSG. Message <= wm_mouselast)
| MSG. Message = wm_mousewheel )){
// Queue user input events for later processing
Havemessage = false;
D-> queueduserinputevents. append (MSG );
}
If (havemessage & (flags & qeventloop: excludesocketnotifiers)
& (Msg. Message = wm_user & msg. hwnd = D-> internalhwnd )){
// Queue socket events for later processing
Havemessage = false;
D-> queuedsocketevents. append (MSG );
}
}
If (! Havemessage ){
// No message-check for signalled objects
For (INT I = 0; I <(INT) ncount; I ++)
Phandles [I] = D-> wineventnotifierlist. at (I)-> handle ();
// Register signal -- slot.
Waitret = msgwaitformultipleobjectsex (ncount, phandles, 0, qs_allinput, mwmo_alertable );
If (havemessage = (waitret = wait_object_0 + ncount ))){
// A new message has arrived, process it
Continue;
}
}
// Events in the event queue need to be processed.
If (havemessage ){
// Process timer events
If (msg. Message = wm_timer ){
// Avoid live-lock by keeping track of the timers we 've ve already sent
Bool found = false;
For (INT I = 0 ;! Found & I <processedtimers. Count (); ++ I ){
Const MSG processed = processedtimers. constdata () [I];
Found = (processed. wparam = msg. wparam & processed. hwnd = msg. hwnd & processed. lparam = msg. lparam );
}
If (found)
Continue;
Processedtimers. append (MSG );
} Else if (msg. Message = wm_quit ){
If (qcoreapplication: instance ())
Qcoreapplication: instance ()-> quit ();
Return false;
}
// Message distribution processing.
If (! Filterevent (& MSG )){
Translatemessage (& MSG );
Qt_wa ({
Dispatchmessage (& MSG );
},{
Dispatchmessagea (& MSG );
});
}
} Else if (waitret> = wait_object_0 & waitret <wait_object_0 + ncount ){
// Process signal -- slot
D-> activateeventnotifier (D-> wineventnotifierlist. At (waitret-wait_object_0 ));
} Else {
// Nothing todo so break
Break;
}
Retval = true;
}

// Still nothing-wait for message or signalled objects
Qthreaddata * Data = D-> threaddata;
Canwait = (! Retval
& Data-> canwait
&&! D-> interrupt
& (Flags & qeventloop: waitformoreevents ));
If (canwait ){
DWORD ncount = D-> wineventnotifierlist. Count ();
Q_assert (ncount <maximum_wait_objects-1 );
For (INT I = 0; I <(INT) ncount; I ++)
Phandles [I] = D-> wineventnotifierlist. at (I)-> handle ();

Emit abouttoblock ();
Waitret = msgwaitformultipleobjectsex (ncount, phandles, infinite, qs_allinput, mwmo_alertable );
Emit awake ();
If (waitret> = wait_object_0 & waitret <wait_object_0 + ncount ){
D-> activateeventnotifier (D-> wineventnotifierlist. At (waitret-wait_object_0 ));
Retval = true;
}
}
} While (canwait );

Return retval;
}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.