學習目標:理解事件過濾器
前置環境
運行環境:qt?creator 4.12
學習內容和效果演示:
Qt 提供了事件過濾器的機制,允許我們在事件到達目標對象之前對事件進行攔截和處理。這在以下情況下非常有用:
-
全局事件處理: 我們可以在應用程序級別安裝一個事件過濾器,攔截所有控件的事件,實現全局性的事件處理邏輯。
-
事件委托: 我們可以讓某個對象代理其他對象的事件處理,比如父窗口處理子控件的事件。
-
事件轉發: 我們可以將事件轉發給其他對象處理,比如將鼠標事件轉發給子控件處理。
理解總結:在對象和事件增加中間層,實現對象和事件是n:1的形式
使用事件過濾器的步驟如下:
-
創建一個事件過濾器對象,實現?
bool eventFilter(QObject*, QEvent*)
?函數。該函數用于處理被過濾的事件。 -
在需要過濾事件的對象上安裝事件過濾器,使用?
installEventFilter()
?函數。 -
在事件過濾器的?
eventFilter()
?函數中處理事件,并返回?true
?表示事件已經被處理,否則返回?false
?讓事件繼續傳播。
實驗
想要實現下列效果,正常思路是給這三個img分別寫對應的鼠標事件,功能效果幾乎一樣。
為了代碼簡化,我想讓這三個img的事件都面向一個事件,則可使用中間層 事件過濾器。
?
?詳細主要代碼
#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{img1.load("C:/Users/jbj/Pictures/test/a.jpg");img2.load("C:/Users/jbj/Pictures/test/b.jpg");img3.load("C:/Users/jbj/Pictures/test/c.jpg");jpg1 =new QLabel;jpg2 =new QLabel;jpg3 =new QLabel;jpg1->setAlignment(Qt::AlignCenter);jpg1->setPixmap(QPixmap::fromImage(img1));jpg2->setAlignment(Qt::AlignCenter);jpg2->setPixmap(QPixmap::fromImage(img2));jpg3->setAlignment(Qt::AlignCenter);jpg3->setPixmap(QPixmap::fromImage(img3));QHBoxLayout* h=new QHBoxLayout;h->addWidget(jpg1);h->addWidget(jpg2);h->addWidget(jpg3);QWidget *wgt=new QWidget(this);QVBoxLayout* v= new QVBoxLayout(wgt);v->addLayout(h);status =new QLabel("鼠標按鍵提示信息!");status->setAlignment(Qt::AlignCenter);v->addWidget(status);setCentralWidget(wgt);//中心控件setGeometry(200,200,600,300);// 安裝事件過濾jpg1->installEventFilter(this);jpg2->installEventFilter(this);jpg3->installEventFilter(this);}MainWindow::~MainWindow()
{
}
/** 這個函數是 QObject 類的一個虛函數,需要在自定義的事件過濾器類中進行重寫。* 它接受兩個參數:
QObject* obj: 事件發生的目標對象。QEvent* event: 正在被處理的事件對象。
函數返回值:
如果事件過濾器處理了這個事件,返回 true。
如果事件過濾器沒有處理這個事件,返回 false。這樣事件就會繼續傳播給目標對象。
*/
bool MainWindow::eventFilter(QObject* watch,QEvent*e) {if (watch == jpg1){if(e->type() == QEvent::MouseButtonPress){// 鼠標移動區域事件,發生在窗戶區域QMouseEvent *m =(QMouseEvent*)e;if(m->buttons() & Qt::LeftButton) status->setText("鼠標左鍵被按下:[左邊圖片]");if(m->buttons() & Qt::MidButton) status->setText("鼠標中鍵被按下:[左邊圖片]");if(m->buttons() & Qt::RightButton) status->setText("鼠標右鍵被按下:[左邊圖片]");//對當前圖片進行放大2倍 創建了一個 QMatrix 對象,用于存儲圖像變換矩陣。QMatrix matrix;matrix.scale(2,2);QImage img =img1.transformed(matrix);jpg1->setPixmap(QPixmap::fromImage(img));}if(e->type()== QEvent::MouseButtonRelease)//鼠標松開事件{status->setText("鼠標按鍵已經釋放:[左邊圖片]");jpg1->setPixmap(QPixmap::fromImage(img1));}}if (watch == jpg2){if(e->type() == QEvent::MouseButtonPress){// 鼠標移動區域事件,發生在窗戶區域QMouseEvent *m =(QMouseEvent*)e;if(m->buttons() & Qt::LeftButton) status->setText("鼠標左鍵被按下:[中間圖片]");if(m->buttons() & Qt::MidButton) status->setText("鼠標中鍵被按下:[中間圖片]");if(m->buttons() & Qt::RightButton) status->setText("鼠標右鍵被按下:[中間圖片]");//對當前圖片進行放大2倍QMatrix matrix;matrix.scale(2,2);jpg2->setPixmap(QPixmap::fromImage(img2.transformed(matrix)));}if(e->type()== QEvent::MouseButtonRelease)//鼠標松開事件{status->setText("鼠標按鍵已經釋放:[中間圖片]");jpg2->setPixmap(QPixmap::fromImage(img2));}}if (watch == jpg3){if(e->type() == QEvent::MouseButtonPress){// 鼠標移動區域事件,發生在窗戶區域QMouseEvent *m =(QMouseEvent*)e;if(m->buttons() & Qt::LeftButton) status->setText("鼠標左鍵被按下:[右邊圖片]");if(m->buttons() & Qt::MidButton) status->setText("鼠標中鍵被按下:[右邊圖片]");if(m->buttons() & Qt::RightButton) status->setText("鼠標右鍵被按下:[右邊圖片]");//對當前圖片進行放大2倍QMatrix matrix;matrix.scale(2,2);jpg3->setPixmap(QPixmap::fromImage(img3.transformed(matrix)));}if(e->type()== QEvent::MouseButtonRelease)//鼠標松開事件{status->setText("鼠標按鍵已經釋放:[右邊圖片]");jpg3->setPixmap(QPixmap::fromImage(img3));}}return QMainWindow::eventFilter(watch,e);
}
總結:
Qt 事件過濾器的主要特點和使用場景:
-
事件攔截和處理:
- 事件過濾器允許我們在事件到達目標對象之前對事件進行攔截和處理。
- 我們可以在?
eventFilter()
?函數中檢查和處理各種類型的事件,如鼠標事件、鍵盤事件、paint 事件等。
-
自定義事件處理邏輯:
- 通過事件過濾器,我們可以實現各種自定義的事件處理邏輯,如全局性的事件處理、事件委托和事件轉發等。
- 這在需要跨控件或跨對象進行事件處理時非常有用。
-
安裝和使用:
- 我們需要創建一個自定義的事件過濾器類,并實現?
eventFilter()
?函數。 - 然后在需要過濾事件的對象上安裝事件過濾器,使用?
installEventFilter()
?函數。
- 我們需要創建一個自定義的事件過濾器類,并實現?
-
常見使用場景:
- 全局事件處理: 在應用程序級別安裝事件過濾器,攔截所有控件的事件,實現全局性的事件處理邏輯。
- 事件委托: 讓某個對象代理其他對象的事件處理,比如父窗口處理子控件的事件。
- 事件轉發: 將事件轉發給其他對象處理,比如將鼠標事件轉發給子控件處理。
-
返回值含義:
- 如果事件過濾器處理了這個事件,返回?
true
。 - 如果事件過濾器沒有處理這個事件,返回?
false
。這樣事件就會繼續傳播給目標對象。
- 如果事件過濾器處理了這個事件,返回?
總之,事件過濾器是 Qt 提供的一個強大的機制,可以幫助我們實現各種復雜的事件處理邏輯。它的核心是?eventFilter()
?函數,通過對這個函數的實現,我們可以根據需求靈活地攔截和處理事件。
最后附上源代碼鏈接
對您有幫助的話,幫忙點個star
28-event-fillter · jbjnb/Qt demo - 碼云 - 開源中國 (gitee.com)