1. Qt事件系統:事件過濾器和事件的發送
Qt事件系統提供了事件過濾器功能,允許部件監控其他多個部件的事件。事件過濾器由installEventFilter()和eventFilter()函數組成,分別用於安裝和處理事件。在myEventFilter項目中,Widget類構造函數中使用installEventFilter()為textEdit和spinBox部件安裝過濾器,eventFilter()函數在Widget類中重新實現,用於截獲並處理兩個子部件事件。在處理事件時,首先判斷部件類型,其次判斷事件類型。對於特定事件,返回true處理該事件,否則返回false以避免重復處理。textEdit部件通過滾輪實現內容放大或縮小,spinBox部件則通過空格設置數值為0。
Qt事件系統還支持事件發送功能,由QCoreApplication類的sendEvent()和postEvent()函數實現。sendEvent()立即處理事件,postEvent()將事件放入等待調度隊列,直至下一次主事件循環運行時處理。sendEvent()中的QEvent對象在事件發送後無法自動刪除,必須在棧上創建。而postEvent()中的QEvent對象在堆上創建,事件隊列自動刪除。在widget.cpp文件構造函數中,通過sendEvent()向spinBox部件發送向上方向鍵被按下的事件。
運行程序時,spinBox部件初始值變為了1,證實已成功發送事件。滾動前後的效果圖如下所示,顯示了使用事件過濾器和發送事件功能的直觀效果。
2. Qt如何捕獲鍵盤事件
您好,Qt鍵盤事件屬於Qt事件系統,所以事件系統中所有規則對按鍵事件都有效。下面關注點在按鍵特有的部分:
focus
一個擁有焦點(focus)的QWidget才可以接受鍵盤事件。有輸入焦點的窗口是活動窗口或活動窗口子窗口或子子窗口等。
焦點移動的方式有以下幾種:
按下Tab或Shift+Tab
注意:文本編譯器(一般需要插入Tab),或者WebView(需要Tab來移動超鏈接焦點) 等
Qt中,需要輸入Tab的地方可以用 Ctrl+Tab 或 Ctrl+Shift+Tab 替代。
點擊一個QWidget
建議:只對接受文本輸入的Widget啟用該功能
按下鍵盤的快捷鍵
QLabel::setBuddy(), QGroupBox,以及 QTabBar 支持
使用滑鼠滾輪
用戶移動焦點
程序將決定被設置focus的Widget的哪一個子Widget獲得焦點
注意:如果一個 Widget 已經 grabKeyboard,所有鍵盤事件將發送到該Widget而不是獲得焦點的Widget
focusPolicy
一個QWidget獲得焦點的方式受 focusPolicy 控制
Qt::TabFocus
通過Tab鍵獲得焦點
Qt::ClickFocus
通過被單擊獲得焦點
Qt::StrongFocus
可通過上面兩種方式獲得焦點
Qt::NoFocus
不能通過上兩種方式獲得焦點(默認值),setFocus仍可使其獲得焦點
keypress和keyrelease
首先,我們要是Widget獲得焦點,一般設置focusPolicy。
然後要對按鍵進行響應,我們只需要直接重載:
keyPressEvent
keyReleaseEvent
注意:
對我們不處理的事件,要調用父類的相應事件處理函數。
如果widget當前沒有焦點,考慮到事件轉發:如果其子widget有焦點,那麼該widget未處理的鍵盤事件將被轉發過來。
有時輸入焦點不在任何窗口中。這種情況發生在所有程序都是最小化的時候。這時,Windows將繼續向活動窗口發送鍵盤消息,但是這些消息與發送給非最小化的活動窗口的鍵盤消息有不同的形式。
QKeyEvent
在windows下,與鍵盤事件有關的有8個消息:
對產生可顯示字元的按鍵組合,Windows不僅給程序發送按鍵消息,而且還發送字元消息
有些鍵不產生字元,這些鍵包括shift鍵、功能鍵、游標移動鍵和特殊字元鍵如Insert和Delete。對於這些鍵,Windows只產生按鍵消息。
這些消息在Qt中只體現在QKeyEvent中。
對字元,可通過 QKeyEvent::text() 獲得
其他鍵,QKeyEvent::key() 獲得一個鍵值
event函數
由於 Tab 鍵被用來切換焦點,這使得它與眾不同。
這是qwidget.cpp的event函數中的代碼片段:
case QEvent::KeyPress:
{
QKeyEvent *k = (QKeyEvent *)event;
bool res = false;
if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier)))
{ //### Add MetaModifier?
if (k->key() == Qt::Key_Backtab || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
res = focusNextPrevChild(false);
else if (k->key() == Qt::Key_Tab)
res = focusNextPrevChild(true);
if (res)
break;
}
keyPressEvent(k);
}
如果我們需要處理Tab鍵,需要重載 event 函數。
3. QT原理與源碼分析之對象級QT事件過濾器
本文簡述了QT原理與源碼分析中的對象級事件過濾器。首先介紹了如何自定義過濾函數,接著闡述了對象級事件過濾器的安裝過程,最後詳細分析了安裝函數的源碼實現。
自定義QT事件過濾器的過濾函數,需在main函數中進行安裝。通過此步驟,可以實現對QT框架中特定事件的過濾與處理,增強程序的靈活性和功能性。
在安裝QT事件過濾器的源代碼部分,明確展示了安裝函數的具體實現。這為開發者提供了實現對象級事件過濾器的步驟指南,便於開發者根據需求進行調用與定製。
進一步,分析了QT對象級別事件過濾器在框架中的調用源代碼。這一部分深入探討了過濾器在實際應用場景中的運作機制,為開發者提供了一個全面理解與實踐對象級事件過濾器的路徑。
總結來看,QT框架不僅支持對象級事件過濾器,還提供了應用級事件過濾器。兩者在原理和源碼實現上具有高度相似性,但本文重點聚焦於對象級事件過濾器。通過詳細解析安裝函數和調用過程,旨在為開發者提供一套實用的實踐指南,助力提升程序處理特定事件的能力。
4. Qt5 事件(event)機制詳解
事件機制是Qt中最復雜且精妙的部分。事件分為兩種主要類型,在用戶與界面交互時產生,如按下滑鼠等操作。這些事件以QEvent對象的形式出現,並通過組件的event函數進行分發。事件對象包含多種屬性,允許事件處理函數根據不同的情況作出響應。例如,當滑鼠左鍵按下時,可以調用特定的事件處理函數,如mousePressEvent,根據QMouseEvent對象的屬性進行相應的操作。
所有事件類都是QEvent類的子類。在處理事件時,首先需要創建自定義的類,繼承自QLabel或類似的基本類,然後重寫相應的事件處理函數。Qt的主程序中需要創建QApplication對象,並調用exec函數啟動事件循環,持續監聽應用程序的事件。當事件發生時,會生成一個QEvent對象,事件循環會將此對象傳入event函數進行分發。
事件的分發通過事件處理器(event handler)完成,事件處理器函數(如mousePressEvent)在事件分發前執行。event函數是一個虛函數,接收一個QEvent類型的參數,當系統生成事件時,會調用此函數。返回值是bool類型,指示是否已處理事件。如果返回true,Qt認為事件已處理完畢,不會將其發送給其他對象,而是繼續處理事件隊列中的下一個事件。反之,如果返回false,事件將繼續傳遞。
Qt中有一種機制叫做事件傳播機制,允許子組件的事件在觸發事件處理器後,繼續傳遞給父組件的event函數進行處理。這種機制通過event函數的返回值來控制。
當使用自定義的事件處理器函數時,最好在事件處理完畢後調用父類的event函數,以便處理其他類型的事件。如果沒有調用父類函數,將導致事件無法傳播到更高層次的組件。
事件過濾器(evenFilter)機制允許攔截特定組件的事件,阻止其向其他組件傳播。通過為組件或其父組件安裝事件過濾器,可以實現特定功能,如在事件處理之前進行自定義操作。事件過濾器也是通過虛函數實現的,接受事件對象和組件對象作為參數。返回true表示事件被攔截,不會繼續傳遞;返回false則表示事件將繼續傳遞。
在實際應用中,可以將事件過濾器應用於QApplication或QCoreApplication對象,以實現全局的事件過濾。需要注意的是,事件過濾器和安裝過濾器的組件必須在同一線程運行,否則過濾器可能無法正常工作。如果組件和過濾器在不同線程間移動,只有當它們回到同一線程時過濾器才會生效。
在使用Qt的事件機制時,應遵循以下步驟:識別事件類型,創建自定義事件處理函數,實現事件分發,利用事件過濾器攔截和處理特定事件。同時,應考慮事件傳播機制和事件處理器的返回值,確保事件正確處理和傳播。