成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

QT類 Qevent事件處理過程 事件過濾器

移動開發
本文介紹的是QT類 Qevent事件處理過程 事件過濾器,事件的操作應該友們很感興趣,先來看你本文介紹。

QT類 Qevent事件處理過程 事件過濾器 是本文要介紹的內容,我們直接進入內容。

事件處理流程:

某個事件發生------>exec()循環會接收到這個事件------>

創建一個事件對象,并將對象傳遞給QObject::event()------>

在QWidget::event()函數中,分配給特定的事件處理函數------>

在QButton的事件處理函數中emit(clicked消息)

前面說到了事件的作用,下面來看看我們如何來接收事件?;貞浺幌虑懊娴拇a,我們在子類中重寫了事件函數,以便讓這些子類按照我們的需要完成某些功能,就像下面的代碼:

  1. void MyLabel::mousePressEvent(QMouseEvent * event)  
  2. {  
  3.         if(event->button() == Qt::LeftButton) {  
  4.                 // do something  
  5.         } else {  
  6.                 QLabel::mousePressEvent(event);  
  7.         }  

上面的代碼和前面類似,在鼠標按下的事件中檢測,如果按下的是左鍵,做我們的處理工作,如果不是左鍵,則調用父類的函數。這在某種程度上說,是把事件向上傳遞給父類去響應,也就是說,我們在子類中“忽略”了這個事件。

我們可以把Qt的事件傳遞看成鏈狀:如果子類沒有處理這個事件,就會繼續向其他類傳遞。其實,Qt的事件對象都有一個accept()函數和ignore()函數。正如它們的名字,前者用來告訴Qt,事件處理函數“接收”了這個事件,不要再傳遞;后者則告訴Qt,事件處理函數“忽略”了這個事件,需要繼續傳遞,尋找另外的接受者。在事件處理函數中,可以使用isAccepted()來查詢這個事件是不是已經被接收了。

事實上,我們很少使用accept()和ignore()函數,而是想上面的示例一樣,如果希望忽略事件,只要調用父類的響應函數即可。記得我們曾經說過,Qt中的事件大部分是protected的,因此,重寫的函數必定存在著其父類中的響應函數,這個方法是可行的。為什么要這么做呢?因為我們無法確認父類中的這個處理函數沒有操作,如果我們在子類中直接忽略事件,Qt不會再去尋找其他的接受者,那么父類的操作也就不能進行,這可能會有潛在的危險。另外我們查看一下QWidget的mousePressEvent()函數的實現:

  1. void QWidget::mousePressEvent(QMouseEvent *event)  
  2. {  
  3.         event->ignore();  
  4.         if ((windowType() == Qt::Popup)) {  
  5.                 event->accept();  
  6.                 QWidget* w;  
  7.                 while ((w = qApp->activePopupWidget()) && w != this){  
  8.                         w->close();  
  9.                         if (qApp->activePopupWidget() == w) // widget does not want to dissappear  
  10.                                 w->hide(); // hide at least  
  11.                 }  
  12.                 if (!rect().contains(event->pos())){  
  13.                         close();  
  14.                 }  
  15.         }  
  16. }  

請注意第一條語句,如果所有子類都沒有覆蓋mousePressEvent函數,這個事件會在這里被忽略掉,這暗示著這個組件不關心這個事件,這個事件就可能被傳遞給其父組件。

不過,事情也不是絕對的。在一個情形下,我們必須使用accept()和ignore()函數,那就是在窗口關閉的時候。如果你在窗口關閉時需要有個詢問對話框,那么就需要這么去寫:

  1. void MainWindow::closeEvent(QCloseEvent * event)  
  2. {  
  3.         if(continueToClose()) {  
  4.                 event->accept();  
  5.         } else {  
  6.                 event->ignore();  
  7.         }  
  8. }  
  9. bool MainWindow::continueToClose()  
  10. {  
  11.         if(QMessageBox::question(this,  
  12.                                             tr("Quit"),  
  13.                                             tr("Are you sure to quit this application?"),  
  14.                                             QMessageBox::Yes | QMessageBox::No,  
  15.                                             QMessageBox::No)  
  16.                 == QMessageBox::Yes) {  
  17.                 return true;  
  18.         } else {  
  19.                 return false;  
  20.         }  

這樣,我們經過詢問之后才能正常退出程序

今天要說的是event()函數。記得之前曾經提到過這個函數,說在事件對象創建完畢后,Qt將這個事件對象傳遞給QObject的event()函數。event()函數并不直接處理事件,而是將這些事件對象按照它們不同的類型,分發給不同的事件處理器(event handler)。

event()函數主要用于事件的分發,所以,如果你希望在事件分發之前做一些操作,那么,就需要注意這個event()函數了。為了達到這種目的,我們可以重寫event()函數。例如,如果你希望在窗口中的tab鍵按下時將焦點移動到下一組件,而不是讓具有焦點的組件處理,那么你就可以繼承QWidget,并重寫它的event()函數,已達到這個目的:

  1. bool MyWidget::event(QEvent *event) {  
  2.         if (event->type() == QEvent::KeyPress) {  
  3.                 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);  
  4.                 if (keyEvent->key() == Qt::Key_Tab) {  
  5.                         // 處理Tab鍵  
  6.                         return true;  
  7.                 }  
  8.         }  
  9.  
  10.         return QWidget::event(event);  

event()函數接受一個QEvent對象,也就是需要這個函數進行轉發的對象。為了進行轉發,必定需要有一系列的類型判斷,這就可以調用QEvent的type()函數,其返回值是QEvent::Type類型的枚舉。我們處理過自己需要的事件后,可以直接return回去,對于其他我們不關心的事件,需要調用父類的event()函數繼續轉發,否則這個組件就只能處理我們定義的事件了。

event()函數返回值是bool類型,如果傳入的事件已被識別并且處理,返回true,否則返回false。如果返回值是true,QApplication會認為這個事件已經處理完畢,會繼續處理事件隊列中的下一事件;如果返回值是false,QApplication會嘗試尋找這個事件的下一個處理函數。

event()函數的返回值和事件的accept()和ignore()函數不同。accept()和ignore()函數用于不同的事件處理器之間的溝通,例如判斷這一事件是否處理;event()函數的返回值主要是通知QApplication的notify()函數是否處理下一事件。為了更加明晰這一點,我們來看看QWidget的event()函數是如何定義的:

  1. bool QWidget::event(QEvent *event) {  
  2.         switch (e->type()) {  
  3.         case QEvent::KeyPress:  
  4.                  keyPressEvent((QKeyEvent *)event);  
  5.                 if (!((QKeyEvent *)event)->isAccepted())  
  6.                         return false;  
  7.                 break;  
  8.         case QEvent::KeyRelease:  
  9.                 keyReleaseEvent((QKeyEvent *)event);  
  10.                 if (!((QKeyEvent *)event)->isAccepted())  
  11.                         return false;  
  12.                 break;  
  13.                 // more...  
  14.         }  
  15.         return true;  

QWidget的event()函數使用一個巨大的switch來判斷QEvent的type,并且分發給不同的事件處理函數。在事件處理函數之后,使用這個事件的isAccepted()方法,獲知這個事件是不是被接受,如果沒有被接受則event()函數立即返回false,否則返回true。

另外一個必須重寫event()函數的情形是有自定義事件的時候。如果你的程序中有自定義事件,則必須重寫event()函數以便將自定義事件進行分發,否則你的自定義事件永遠也不會被調用。

創建事件過濾器和安裝事件過濾器

Qt創建了QEvent事件對象之后,會調用QObject的event()函數做事件的分發。有時候,你可能需要在調用event()函數之前做一些另外的操作,比如,對話框上某些組件可能并不需要響應回車按下的事件,此時,你就需要重新定義組件的event()函數。如果組件很多,就需要重寫很多次event()函數,這顯然沒有效率。為此,你可以使用一個事件過濾器,來判斷是否需要調用event()函數。

QOjbect有一個eventFilter()函數,用于建立事件過濾器。這個函數的簽名如下:

  1. virtual bool QObject::eventFilter ( QObject * watched, QEvent * event ) 

如果watched對象安裝了事件過濾器,這個函數會被調用并進行事件過濾,然后才輪到組件進行事件處理。在重寫這個函數時,如果你需要過濾掉某個事件,例如停止對這個事件的響應,需要返回true。

  1. bool MainWindow::eventFilter(QObject *obj, QEvent *event)  
  2.  {  
  3.          if (obj == textEdit) {  
  4.                  if (event->type() == QEvent::KeyPress) {  
  5.                          QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);  
  6.                          qDebug() << "Ate key press" << keyEvent->key();  
  7.                          return true;  
  8.                  } else {  
  9.                          return false;  
  10.                  }  
  11.          } else {  
  12.                  // pass the event on to the parent class  
  13.                  return QMainWindow::eventFilter(obj, event);  
  14.          }  
  15.  } 

上面的例子中為MainWindow建立了一個事件過濾器。為了過濾某個組件上的事件,首先需要判斷這個對象是哪個組件,然后判斷這個事件的類型。例如,我不想讓textEdit組件處理鍵盤事件,于是就首先找到這個組件,如果這個事件是鍵盤事件,則直接返回true,也就是過濾掉了這個事件,其他事件還是要繼續處理,所以返回false。對于其他組件,我們并不保證是不是還有過濾器,于是最保險的辦法是調用父類的函數。

在創建了過濾器之后,下面要做的是安裝這個過濾器。安裝過濾器需要調用installEventFilter()函數。這個函數的簽名如下:

  1. void QObject::installEventFilter ( QObject * filterObj ) 

這個函數是QObject的一個函數,因此可以安裝到任何QObject的子類,并不僅僅是UI組件。這個函數接收一個QObject對象,調用了這個函數安裝事件過濾器的組件會調用filterObj定義的eventFilter()函數。例如,textField.installEventFilter(obj),則如果有事件發送到textField組件是,會先調用obj->eventFilter()函數,然后才會調用textField.event()。

當然,你也可以把事件過濾器安裝到QApplication上面,這樣就可以過濾所有的事件,已獲得更大的控制權。不過,這樣做的后果就是會降低事件分發的效率。

如果一個組件安裝了多個過濾器,則最后一個安裝的會最先調用,類似于堆棧的行為。

注意,如果你在事件過濾器中delete了某個接收組件,務必將返回值設為true。否則,Qt還是會將事件分發給這個接收組件,從而導致程序崩潰。

事件過濾器和被安裝的組件必須在同一線程,否則,過濾器不起作用。另外,如果在install之后,這兩個組件到了不同的線程,那么,只有等到二者重新回到同一線程的時候過濾器才會有效。

事件的調用最終都會調用QCoreApplication的notify()函數,因此,最大的控制權實際上是重寫QCoreApplication的notify()函數。由此可以看出,Qt事件處理實際上是分層五個層次:重定義事件處理函數,重定義event()函數,為單個組件安裝事件過濾器,為QApplication安裝事件過濾器,重定義QCoreApplication的notify()函數。這幾個層次的控制權是逐層增大的。

小結:關于QT類 Qevent事件處理過程 事件過濾器 的內容介紹按了,希望本文對你有所幫助。

責任編輯:zhaolei 來源: 互聯網
相關推薦

2011-06-29 16:14:59

Qt 事件 過濾器

2011-07-04 14:00:11

QT QEvent

2021-07-05 15:22:03

Servlet過濾器客戶端

2024-01-05 09:04:35

隆過濾器數據結構哈希函數

2011-07-01 14:20:59

Qt 事件

2011-07-01 14:14:34

Qt 事件

2024-11-04 08:45:48

布隆過濾器元數據指紋值

2009-07-08 15:30:56

Servlet過濾器

2009-07-14 09:09:08

Swing模型過濾器

2009-07-08 16:07:04

Servlet過濾器配

2009-09-29 13:55:23

Hibernate設置

2011-08-29 11:25:29

QTWebKit鼠標

2009-06-18 10:13:00

Hibernate過濾

2025-04-21 00:50:50

2017-07-18 14:10:31

大數據Apache Flum過濾器

2009-07-08 17:33:37

Servlet過濾器

2009-09-25 15:19:44

Hibernate過濾

2011-07-04 14:50:49

QT Event 事件

2011-08-29 14:59:26

QtEvent事件

2023-04-14 09:01:25

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产亚洲精品久久久优势 | 国产一区www | 日本一级淫片免费啪啪3 | 国产欧美一区二区精品忘忧草 | 我想看一级黄色毛片 | 久久久2o19精品 | 欧美区在线 | 国产区精品在线观看 | 欧美日韩综合一区 | 夜色www国产精品资源站 | 精品国产欧美一区二区 | 亚洲视频在线免费观看 | 国产精品国产三级国产aⅴ中文 | 伊人春色成人网 | 日韩一区二区不卡 | 国产精品久久久99 | 成人精品国产免费网站 | 亚洲一区二区视频在线播放 | 国产黄色在线观看 | 日韩一区二区三区av | 国产精品九九视频 | 综合久久综合久久 | 黄色网页在线观看 | 欧美高清性xxxxhdvideosex | 亚洲欧美在线免费观看 | 天天干天天玩天天操 | 99精品国自产在线 | 欧美亚洲一区二区三区 | 亚洲精品一二三 | 夜夜夜夜草| av网站在线看| 亚洲一区二区精品视频在线观看 | 精品日韩一区二区三区 | 国产一区二区精品在线 | 亚洲精品国产一区 | 日韩免费高清视频 | 人人看人人搞 | 亚洲美女一区 | 91成人精品 | 一级做a | 成人水多啪啪片 |