程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Qt學習之路(23):自定義事件

Qt學習之路(23):自定義事件

編輯:關於C++

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved