Qt 自定義事件

2018-10-06 20:05 更新

自定義事件

這部分將作為 Qt 事件部分的結(jié)束。我們在前面已經(jīng)從大概上了解了 Qt 的事件機制。下面要說的是如何自定義事件。

Qt 允許你創(chuàng)建自己的事件類型,這在多線程的程序中尤其有用,當然,也可以用在單線程的程序中,作為一種對象間通訊的機制。那么,為什么我需要使用事件,而不是使用信號槽呢?主要原因是,事件的分發(fā)既可以是同步的,又可以是異步的,而函數(shù)的調(diào)用或者說是槽的回調(diào)總是同步的。事件的另外一個好處是,它可以使用過濾器。

Qt 中的自定義事件很簡單,同其他類似的庫的使用很相似,都是要繼承一個類進行擴展。在 Qt 中,你需要繼承的類是 QEvent。注意,在 Qt3中,你需要繼承的類是 QCustomEvent,不過這個類在 Qt4中已經(jīng)被廢除(這里的廢除是不建議使用,并不是從類庫中刪除)。

繼承 QEvent 類,你需要提供一個 QEvent::Type 類型的參數(shù),作為自定義事件的類型值。這里的QEvent::Type 類型是 QEvent 里面定義的一個 enum,因此,你是可以傳遞一個 int 的。重要的是,你的事件類型不能和已經(jīng)存在的 type 值重復(fù),否則會有不可預(yù)料的錯誤發(fā)生!因為系統(tǒng)會將你的事件當做系統(tǒng)事件進行派發(fā)和調(diào)用。在 Qt 中,系統(tǒng)將保留0 - 999的值,也就是說,你的事件 type 要大于999. 具體來說,你的自定義事件的 type 要在 QEvent::User 和 QEvent::MaxUser 的范圍之間。其中,QEvent::User 值是1000,QEvent::MaxUser 的值是65535。從這里知道,你最多可以定義64536個事件,相信這個數(shù)字已經(jīng)足夠大了!但是,即便如此,也只能保證用戶自定義事件不能覆蓋系統(tǒng)事件,并不能保證自定義事件之間不會被覆蓋。為了解決這個問題,Qt 提供了一個函數(shù):registerEventType(),用于自定義事件的注冊。該函數(shù)簽名如下:

static int QEvent::registerEventType ( int hint = -1 );

函數(shù)是 static 的,因此可以使用 QEvent 類直接調(diào)用。函數(shù)接受一個 int 值,其默認值為-1,返回值是創(chuàng)建的這個 Type 類型的值。如果 hint 是合法的,不會發(fā)生任何覆蓋,則會返回這個值;如果hint 不合法,系統(tǒng)會自動分配一個合法值并返回。因此,使用這個函數(shù)即可完成 type 值的指定。這個函數(shù)是線程安全的,因此不必另外添加同步。

你可以在 QEvent 子類中添加自己的事件所需要的數(shù)據(jù),然后進行事件的發(fā)送。Qt 中提供了兩種發(fā)送方式:

static bool QCoreApplication::sendEvent(QObjecy receiver, QEvent event):事件被 QCoreApplication 的 notify()函數(shù)直接發(fā)送給 receiver 對象,返回值是事件處理函數(shù)的返回值。使用這個函數(shù)必須要在棧上創(chuàng)建對象,例如:

QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
QApplication::sendEvent(mainWindow, &event);

static bool QCoreApplication::postEvent(QObject receiver, QEvent event):事件被 QCoreApplication 追加到事件列表的最后,并等待處理,該函數(shù)將事件追加后會立即返回,并且注意,該函數(shù)是線程安全的。另外一點是,使用這個函數(shù)必須要在堆上創(chuàng)建對象,例如:

QApplication::postEvent(object, new MyEvent(QEvent::registerEventType(2048)));

這個對象不需要手動 delete,Qt 會自動 delete 掉!因此,如果在 post 事件之后調(diào)用 delete,程序可能會崩潰。另外,postEvent()函數(shù)還有一個重載的版本,增加一個優(yōu)先級參數(shù),具體請參見API。通過調(diào)用 sendPostedEvent()函數(shù)可以讓已提交的事件立即得到處理。

如果要處理自定義事件,可以重寫 QObject 的 customEvent()函數(shù),該函數(shù)接收一個 QEvent 對象作為參數(shù)。注意,在 Qt3中這個參數(shù)是 QCustomEvent 類型的。你可以像前面介紹的重寫 event()函數(shù)的方法去重寫這個函數(shù):

void CustomWidget::customEvent(QEvent *event) {
        CustomEvent *customEvent = static_cast<CustomEvent *>(event);
        // ....
}

另外,你也可以通過重寫 event()函數(shù)來處理自定義事件:

bool CustomWidget::event(QEvent *event) {
        if (event->type() == MyCustomEventType) {
                CustomEvent *myEvent = static_cast<CustomEvent *>(event);
                // processing...
                return true;
        }

        return QWidget::event(event);
}

這兩種辦法都是可行的。

好了,至此,我們已經(jīng)概略的介紹了 Qt 的事件機制,包括事件的派發(fā)、自定義等一系列的問題。下面的章節(jié)將繼續(xù)我們的學習之路!

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

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號