Qt 自定義事件







    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(objectnew 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);
}

這兩種辦法都是可行的。

本文出自 “豆子空間” 博客,請務必保留此出處http://devbean.blog.51cto.com/448512/232314

發佈了7 篇原創文章 · 獲贊 13 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章