Qt允許你創建自己的事件類型,這在多線程的程序中尤其有用,當然,也可以用在單線程的程序中,作為一種對象間通訊的機制。那麼,為什麼我需要使用事件,而不是使用信號槽呢?主要原因是,事件的分發既可以是同步的,又可以是異步的,而函數的調用或者說是槽的回調總是同步的。事件的另外一個好處是,它可以使用過濾器。
Qt中的自定義事件很簡單,同其他類似的庫的使用很相似,都是要繼承一個類進行擴展。在Qt中,你需要繼承的類是QEvent。注意,在Qt3中,你需要繼承的類是QCustomEvent,不過這個類在Qt4中已經被廢除(這裡的廢除是不建議使用,並不是從類庫中刪除)。
繼承QEvent類,你需要提供一個QEvent::Type類型的參數,作為自定義事件的類型值。這裡的QEvent::Type類型是QEvent裡面定義的一個enum,因此,你是可以傳遞一個int的。重要的是,你的事件類型不能和已經存在的type值重復,否則會有不可預料的錯誤發生!因為系統會將你的事件當做系統事件進行派發和調用。在Qt中,系統將保留0 - 999的值,也就是說,你的事件type要大於999. 具體來說,你的自定義事件的type要在QEvent::User和QEvent::MaxUser的范圍之間。其中,QEvent::User值是 1000,QEvent::MaxUser的值是65535。從這裡知道,你最多可以定義64536個事件,相信這個數字已經足夠大了!但是,即便如此,也只能保證用戶自定義事件不能覆蓋系統事件,並不能保證自定義事件之間不會被覆蓋。為了解決這個問題,Qt提供了一個函數:registerEventType(),用於自定義事件的注冊。該函數簽名如下:
static int QEvent::registerEventType ( int hint = -1 );
函數是static的,因此可以使用QEvent類直接調用。函數接受一個int值,其默認值為-1,返回值是創建的這個Type類型的值。如果hint是合法的,不會發生任何覆蓋,則會返回這個值;如果hint不合法,系統會自動分配一個合法值並返回。因此,使用這個函數即可完成type值的指定。這個函數是線程安全的,因此不必另外添加同步。
你可以在QEvent子類中添加自己的事件所需要的數據,然後進行事件的發送。Qt中提供了兩種發送方式:
* static bool QCoreApplication::sendEvent(QObjecy * receiver, QEvent * event):事件被QCoreApplication的notify()函數直接發送給receiver對象,返回值是事件處理函數的返回值。使用這個函數必須要在棧上創建對象,例如:
QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
QApplication::sendEvent(mainWindow, &event);
* static bool QCoreApplication::postEvent(QObject * receiver, QEvent * event):事件被QCoreApplication追加到事件列表的最後,並等待處理,該函數將事件追加後會立即返回,並且注意,該函數是線程安全的。另外一點是,使用這個函數必須要在堆上創建對象,例如:
QApplication::postEvent(object, new MyEvent(QEvent::registerEventType(2048)));
這個對象不需要手動delete,Qt會自動delete掉!因此,如果在post事件之後調用delete,程序可能會崩潰。另外,postEvent()函數還有一個重載的版本,增加一個優先級參數,具體請參見API。通過調用sendPostedEvent()函數可以讓已提交的事件立即得到處理。
如果要處理自定義事件,可以重寫QObject的customEvent()函數,該函數接收一個QEvent對象作為參數。注意,在Qt3中這個參數是QCustomEvent類型的。你可以像前面介紹的重寫event()函數的方法去重寫這個函數:
void CustomWidget::customEvent(QEvent *event) {
CustomEvent *customEvent = static_cast<CustomEvent *>(event);
// ....
}
另外,你也可以通過重寫event()函數來處理自定義事件:
bool CustomWidget::event(QEvent *event) {
if (event->type() == MyCustomEventType) {
CustomEvent *myEvent = static_cast<CustomEvent *>(event);
// processing...
return true;
}
return QWidget::event(event);
}
這兩種辦法都是可行的。
好了,至此,我們已經概略的介紹了Qt的事件機制,包括事件的派發、自定義等一系列的問題。下面的章節將繼續我們的學習之路!
出處:http://devbean.blog.51cto.com/448512/232314