The Event System
?
?
?
The Event System
在Qt中,事件是繼承了虛擬類QEvent的對象,它代表了程序所發生的事情或者程序需要知道的一個外部活動的結果。事件可以被任意?QObject子類的實例接收和處理,是與widgets密切相關。本文描述了在一個典型的程序中事件是如何被傳送和處理的。
How Events are Delivered
當發生一個事件,Qt通過構造一個適當的?QEvent子類的實例來創建事件對象來代表它,并通過調用vevent()函數把它傳送到特定的?QObject?實例。
該函數本身不處理事件:根據傳送的事件類型,它為特定的時間類型調用一個事件處理程序,并根據事件是被接受或忽略發送一個響應。
一些事件,如QMouseEvent?和?QKeyEvent來自windows系統。如QTimerEvent,?來自其他來源,一些來自程序本身。
Event Types
大多數的事件類型有特別的類,尤其是?QResizeEvent,?QPaintEvent,?QMouseEvent,?QKeyEvent,andQCloseEvent.?,它們都繼承了QEvent?和添加了特殊的函數。如?QResizeEvent?添加了?size()和?oldSize()函數使得widgets?可以獲得其改變的規模。
一些類支持多于一種實際的事件類型。?QMouseEvent?支持鼠標按下,雙擊,移動和其他相關操作。
每個事件都有一個定義在QEvent::Type的相關的類型,它可以用作運行時的類型信息以快速確定事件對象是構造自哪個子類。
由于程序需要多種復雜的方式的響應,Qt的事件傳送機制也是靈活的。QCoreApplication::notify()文檔對稱進行了確切的描述。
Event Handlers
通常事件被傳送的方法是調用一個虛函數。例如,?QPaintEvent?通過調用?QWidget::paintEvent().而被傳送。該虛函數復雜作出適當的響應,通常是重繪widget。如果在你實現的虛函數里不能完成所需要的功能,可以調用基類的實現。
例如,下面的代碼處理了自定義的checkbox?鼠標左鍵按下事件,把其他按鍵按下的事件傳送給基類QCheckBox?:
void MyCheckBox::mousePressEvent(QMouseEvent*event) { ??? if (event->button() ==Qt::LeftButton) { ??????? // handle left mouse button here ??? } else { ??????? // pass on other buttons to base class ??????? QCheckBox::mousePressEvent(event); ??? } }如果你想取代基類的函數,你必須自己實現每件事。然而,如果你只想擴展基類的功能,你可以實現自己想實現的部分,在任何你不想處理情況,可以調用基類來獲得默認的處理。
偶爾,可能沒有特定事件的函數,或者特定事件的函數功能不充分。最常見的例子包含Tab 按下。通常,?QWidget攔截事件來移動鍵盤焦點,但是有的widget需要自己處理Tab 按下事件。
這些對象可以重新實現?QObject::event(),,一般的事件處理程序,可以在通常的事件處理之前或之后對它們的事件進行處理,或者完全取代整個函數的。一個既攔截Tab 也有自定義事件的widget?可能包含以下的event()?函數:
bool MyWidget::event(QEvent*event) { ??? if (event->type() ==QEvent::KeyPress) { ??? QKeyEvent*ke =static_cast<QKeyEvent*>(event); ??? if (ke->key() ==Qt::Key_Tab) { ??????? // special tab handling here ??????? returntrue; ??? } ??? } elseif (event->type() == MyCustomEventType) { ??? MyCustomEvent *myEvent =static_cast<MyCustomEvent *>(event); ??? // custom event handling here ??? returntrue; ??? } ? ??? returnQWidget::event(event); }我們注意到對于沒有處理的所有情況都調用了QWidget::event()?,而且返回值表明了事件是否被處理。返回值true阻止了事件被傳遞給其他對象。
Event Filters
有時一個對象需要檢查并可能攔截被傳送給其他對象的事件。例如,對話框一般需要為一下widget過濾鍵盤按鍵事件。例如,修改返回鍵處理。
QObject::installEventFilter()設置了eventfilter,,在目標對象的QObject::eventFilter()?函數里接收事件。事件過濾器在目標對象之前處理事件,根據需要允許對事件進行檢查和丟棄??梢杂?QObject::removeEventFilter()函數移除一個已經存在的事件過濾器。
當一個過濾器對象的eventFilter()?實現被調用,它可以接受或不接受事件,允許或拒絕更進一步的處理事件。如果所有的事件過濾器允許更進一步的處理事件,事件將被發送給目標對象本身。如果其中某個事件停止處理,目標對象和后面一些事件過濾器都接收不到該事件。
bool FilterObject::eventFilter(QObject*object,QEvent*event) { ??? if (object == target && event->type() ==QEvent::KeyPress) { ??????? QKeyEvent*keyEvent =static_cast<QKeyEvent*>(event); ??????? if (keyEvent->key() ==Qt::Key_Tab) { ??????????? // Special tab handling ??????????? returntrue; ??????? } else ??????????? returnfalse; ??? } ??? returnfalse; }以上代碼演示了另一種攔截Tab按鍵事件并發送到特定目標widget的方法。在這種情況下,事件過濾器處理了相關的事件并返回true阻止事件被進一步處理。其他的事件則被忽略,事件過濾器返回false以允許它們被發送到目標widget,通過任何已經安裝的事件過濾器。
為整個程序過濾所有的事件也是可能的,通過為?QApplication?或QCoreApplication?安裝事件過濾器。這樣的全局事件過濾器將會在特定對象的過濾器之前被調用。這很強大,但是也會使得整個程序的事件發送變慢。
Sending Events
很多程序想創建和發送自己的事件。你可以用像Qt的事件循環一樣的方法發送事件,通過構造合適的事件對象并用QCoreApplication::sendEvent()和QCoreApplication::postEvent().發送事件。
sendEvent()立即處理事件。當它返回,事件過濾器和對象本身已經處理了事件。對于很多事件類型,有一個isAccepted()函數用來獲取最近的處理過程事件是被接受還是不被接受。
postEvent()把事件傳遞到隊列等待分發。下一次主事件循環運行,它進行一些優化將分發所有的隊列中的事件。例如,有一些resize?事件,將被壓縮成一個事件。同樣的應用與paint事件:QWidget::update()調用?postEvent(),它消除閃爍和增加速度以避免多次重繪。
postEvent()在對象初始化過程中也被用到,因為發出的事件將在對象的初始化完成之后立即分發。當實現一個widget,意識到事件可能在其生命期的早期被分發這很重要,在其構造函數中,確保在早期初始化成員變量,在其有機會接收到事件之前。
要創建自定義的事件類型,需要定義一個事件號,必須大于?QEvent::User.
?
?
總結
以上是生活随笔為你收集整理的The Event System的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CutJS – 用于 HTML5 游戏开
- 下一篇: discuz x2.5插件开发傻瓜图文教