Anatomy of event distribution source code in QT
Event delivery sequence in QT:
In a supposed program, it goes into an event loop, accepts the events generated by the system, and distributes them, all in exec.
The following examples illustrate:
1) First Look at the following example code:
[CPP]View Plaincopy
- int main (int argc, char *argv[])
- {
- Qapplication A (argc, argv);
- MouseEvent W;
- W.show ();
- return a.exec ();
- }
2) a.exec into the event loop, call is qapplication::exec ();
[CPP]View Plaincopy
- int Qapplication::exec ()
- {
- return <span style="color: #ff6666;" >qguiapplication::exec ();</span>
- }
3) Qapplication::exec () is called qguiapplication::exec ();
[CPP]View Plaincopy
- int Qguiapplication::exec ()
- {
- #ifndef qt_no_accessibility
- Qaccessible::setrootobject (Qapp);
- #endif
- return qcoreapplication::exec ();
- }
4) Qguiapplication::exec () is called qcoreapplication::exec ();
[CPP]View Plaincopy
- int Qcoreapplication::exec ()
- {
- if (! Qcoreapplicationprivate::checkinstance ("exec"))
- return-1;
- Qthreaddata *threaddata = Self->d_func ()->threaddata;
- if (threaddata! = Qthreaddata::current ()) {
- Qwarning ("%s::exec:must is called from the main thread", Self->metaobject ()->classname ());
- return-1;
- }
- 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;
- Self->d_func ()->abouttoquitemitted = false;
- int returncode = eventloop.exec ();
- Threaddata->quitnow = false;
- if (self) {
- Self->d_func ()->in_exec = false;
- if (!self->d_func ()->abouttoquitemitted)
- Emit Self->abouttoquit (Qprivatesignal ());
- Self->d_func ()->abouttoquitemitted = true;
- Sendpostedevents (0, Qevent::D eferreddelete);
- }
- return ReturnCode;
- }
5) qcoreapplication::exec () call Eventloop.exec () for Event loop;
[CPP]View Plaincopy
- int qeventloop::exec (Processeventsflags flags)
- {
- Q_d (Qeventloop);
- //we need to protect from race condition with Qthread::exit
- Qmutexlocker Locker (&static_cast<qthreadprivate *> (qobjectprivate::get ( d->threaddata-> Thread)) (->mutex);
- if (d->threaddata->quitnow)
- return-1;
- if (d->inexec) {
- Qwarning ("Qeventloop::exec:instance%p have already called EXEC ()", this );
- return-1;
- }
- struct Loopreference {
- Qeventloopprivate *d;
- Qmutexlocker &locker;
- bool Exceptioncaught;
- Loopreference (qeventloopprivate *d, Qmutexlocker &locker): D (d), Locker (Locker), Exceptioncaught (true)
- {
- D->inexec = true;
- D->exit = false;
- ++d->threaddata->looplevel;
- D->threaddata->eventloops.push (D->q_func ());
- Locker.unlock ();
- }
- ~loopreference ()
- {
- if (exceptioncaught) {
- Qwarning ("Qt has caught a exception thrown from an event handler. throwing\n "
- "Exceptions from a event handler is not a supported in Qt. You must\n "
- "Reimplement qapplication::notify () and catch all Exceptions there.\n");
- }
- Locker.relock ();
- Qeventloop *eventloop = D->threaddata->eventloops.pop ();
- q_assert_x (EventLoop = = D->q_func (), "qeventloop::exec ()", "Internal Error");
- Q_unused (EventLoop); //--release warning
- D->inexec = false;
- --d->threaddata->looplevel;
- }
- };
- Loopreference ref (d, Locker);
- //Remove posted Quit events when entering a new event loop
- Qcoreapplication *app = Qcoreapplication::instance ();
- if (app && app->thread () = = Thread ())
- Qcoreapplication::removepostedevents (app, qevent::quit);
- While (!d->exit)
- Processevents (Flags | waitformoreevents | EVENTLOOPEXEC);
- Ref.exceptioncaught = false;
- return d->returncode;
- }
6) eventloop.exec () call Qcoreapplication's processevents for event distribution; 7) call Notify for distribution
Qcoreapplication::sendevent, Qcoreapplication::p ostevent and Qcoreapplication::sendpostedevents all call notify for event distribution;
[CPP]View Plaincopy
- BOOL Qcoreapplication::notify (Qobject *receiver, qevent *event)
- {
- Q_d (qcoreapplication);
- //No events is delivered after ~qcoreapplication () have started
- if (qcoreapplicationprivate::is_app_closing)
- return true;
- if (receiver = = 0) { //serious error
- Qwarning ("qcoreapplication::notify:unexpected null receiver");
- return true;
- }
- #ifndef Qt_no_debug
- D->checkreceiverthread (receiver);
- #endif
- return Receiver->iswidgettype ()? false: <span style="color: #ff6666;" > d->notify_helper</span> (receiver, event);
- }
8) Notify call Notify_helper for event distribution;
[CPP]View Plaincopy
- BOOL Qcoreapplicationprivate::notify_helper (Qobject *receiver, qevent * Event)
- {
- //Send to all application event filters
- if (sendthroughapplicationeventfilters (receiver, event))
- return true;
- //Send to all receiver event filters
- if (sendthroughobjecteventfilters (receiver, event))
- return true;
- //Deliver the event
- return receiver->event (event);
- }
9) from the code in the 8th step above, you can see the event passing
The order of delivery is first passed to the global event filter, then to the target object's event filter, and finally passed to the target object.
http://blog.csdn.net/chenlong12580/article/details/25009095
Anatomy of the event distribution source in QT (total 8 steps, the sequence is very clear: the global event filter, then the event filter passed to the target object, eventually passed to the target object)