qt中sendevent_Qt中postEvent和sendEvent函数
Qt中postEvent和sendEvent函數(shù)
部分內(nèi)容參考http://blog.csdn.net/lvmengzou/article/details/65450908
qt事件循環(huán)需要維護(hù)一個(gè)事件隊(duì)列,在Qt的main函數(shù)中最后一般調(diào)用QApplication::exec()成員函數(shù)來(lái)保持程序?qū)κ录?duì)列的處理,exec()的實(shí)質(zhì)是不停調(diào)用processEvent()函數(shù)從隊(duì)列中獲取事件,并處理,然后刪除,postEvent的作用就是發(fā)送一個(gè)事件到此隊(duì)列中,由于刪除隊(duì)列中事件調(diào)用delete運(yùn)算符,所以,postEvent()傳遞的事件一定要是動(dòng)態(tài)分配的。
sendEvent()函數(shù)直接跳過(guò)事件循環(huán)隊(duì)列,直接調(diào)用notify()函數(shù)發(fā)送事件到目標(biāo)對(duì)象,并等待事件處理結(jié)果,所以其傳遞的事件直接在棧上分配即可,(postEvent()函數(shù)只負(fù)責(zé)添加事件到隊(duì)列,不等待事件處理結(jié)果)。
sendEvent調(diào)用關(guān)系如下:
inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
QCoreApplication::notifyInternal(QObject * receiver, QEvent * event)
QCoreApplication::notify(QObject * receiver, QEvent *event)
QCoreApplicationPrivate::notify_helper(QObject * receiver, QEvent * event)
最終調(diào)用receiver->event(event);
PostEvent()函數(shù)只是單純添加事件到postEventList
void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
{
postEvent(receiver, event, Qt::NormalEventPriority);
}
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
...
QThreadData * volatile * pdata = &receiver->d_func()->threadData; //得到線程信息
QThreadData *data = *pdata;
if (!data) {
// posting during destruction? just delete the event to prevent a leak
delete event;
return;
}
// lock the post event mutex
data->postEventList.mutex.lock();
// if object has moved to another thread, follow it
while (data != *pdata) { //在這里判斷receiver線程信息是否發(fā)生變化。(有可能是另外一個(gè)線程調(diào)用用receiver->moveToThread)
data->postEventList.mutex.unlock();
data = *pdata;
if (!data) {
// posting during destruction? just delete the event to prevent a leak
delete event;
return;
}
data->postEventList.mutex.lock();
}
//這里postEventList還是被鎖著的。
// if this is one of the compressible events, do compression
if (receiver->d_func()->postedEvents
&& self && self->compressEvent(event, receiver, &data->postEventList)) {
data->postEventList.mutex.unlock();//這個(gè)事件有可能被壓縮(實(shí)際上是發(fā)現(xiàn)隊(duì)列中有這個(gè)事件還沒(méi)有被處理,且這個(gè)事件是可以被壓縮的,例如paintevent)
return;
}
event->posted = true;
++receiver->d_func()->postedEvents;
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
// remember the current running eventloop for DeferredDelete
// events posted in the receiver's thread
event->d = reinterpret_cast(quintptr(data->loopLevel)); //receiver即將被析構(gòu)?
}
//將事件添加到postEventList中,注意這里的優(yōu)先級(jí)第一個(gè)最高,最后一個(gè)優(yōu)先級(jí)最低
if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) {
// optimization: we can simply append if the last event in
// the queue has higher or equal priority
data->postEventList.append(QPostEvent(receiver, event, priority));
} else {
// insert event in descending priority order, using upper
// bound for a given priority (to ensure proper ordering
// of events with the same priority)
QPostEventList::iterator begin = data->postEventList.begin()
+ data->postEventList.insertionOffset,
end = data->postEventList.end();
QPostEventList::iterator at = qUpperBound(begin, end, priority);
data->postEventList.insert(at, QPostEvent(receiver, event, priority));
}
data->canWait = false;
data->postEventList.mutex.unlock();//在這里解除鎖
//receiver所在的線程調(diào)用eventDispatcher處理postEventList
if (data->eventDispatcher)
data->eventDispatcher->wakeUp();
}
如果想查看Qt中QApplication::exec()函數(shù)是如何傳遞事件到目標(biāo)對(duì)象,并根據(jù)notify返回值和事件isAccept()的返回值決定是否傳遞事件到目標(biāo)對(duì)象的父對(duì)象,可以重載目標(biāo)對(duì)象的事件處理函數(shù),并在事件處理函數(shù)中加入斷點(diǎn),開(kāi)始調(diào)試,然后在可執(zhí)行程序界面上觸發(fā)事件處理函數(shù),程序就會(huì)在事件處理函數(shù)的斷點(diǎn)處停止,然后逐級(jí)返回,查看整個(gè)調(diào)用情況,從processEvent()函數(shù)到最終我們重載的事件處理函數(shù),至少有20層函數(shù)調(diào)用。(調(diào)試之前要安裝Qt源碼組件)
總結(jié)
以上是生活随笔為你收集整理的qt中sendevent_Qt中postEvent和sendEvent函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 拆开一看竟然是二修电脑拆开一看竟然是二修
- 下一篇: 为什么哲学是最难的学科_什么是哲学哲学对