Qt的事件

来源:http://www.cnblogs.com/JayChen1996/archive/2017/03/22/6600722.html
-Advertisement-
Play Games

Qt的事件機制 事件過濾器: 可以讓一個對象偵聽攔截另外一個對象的事件。 實現原理: 在所有Qt對象的基類:QObject中有一個 類型為:QObjectList 名字為:eventFilters 的成員變數,當A給B安裝了事件過濾器後 B的eventList中就會保存A對象的指針, 在B處理事件之 ...


Qt的事件機制

事件過濾器:
  可以讓一個對象偵聽攔截另外一個對象的事件。
  實現原理:
  在所有Qt對象的基類:QObject中有一個
  類型為:QObjectList
  名字為:eventFilters
  的成員變數,當A給B安裝了事件過濾器後
  B的eventList中就會保存A對象的指針,
  在B處理事件之前,會先檢查eventList是
  否為空,如果不為空,就會調用事件過濾器函數eventFilter(),如果eventFilter()返回true,表示事件已經被處理完畢,Qt將直接返回進行下一事件處理,如果為false,事件將接著被送往剩下的事件過濾器或者是目標對象進行處理。

 

按照事件的起源將事件分為三類:

  Spontaneous事件-----自發事件

  由視窗系統產生,被放到系統隊列中,通過事件迴圈逐個處理。

  Posted事件

  由Qt或是應用程式產生,被Qt組成隊列,再通過事件迴圈處理。

  sent事件

  由Qt或是應用程式產生,但他們被直接發送到目標對象。

Qt事件迴圈的過程

  在調用QApplication::exec()時,程式進入了Qt的事件迴圈,

  事件迴圈的大致示意

 1 while (!exit_was_called) 
 2 { 
 3     while(!posted_event_queue_is_empty) 
 4     { 
 5         process_next_posted_event(); 
 6     } 
 7     while(!spontaneous_event_queue_is_empty) 
 8     { 
 9         process_next_spontaneous_event(); 
10     } 
11     while(!posted_event_queue_is_empty) 
12     { 
13         process_next_posted_event(); 
14     } 
15 }

  可以看出,程式首先處理所有的posted事件,知道隊列空,再處理Spontaneous事件,再處理因Spontaneous事件產生的posted事件。

  send事件不在事件迴圈內,因為他們不進入事件隊列而是直接發送給目標對象

 

實例paint()事件:

  當一個widget第一次可見,或者是被遮擋後可見,視窗產生一個(Spontaneous)paint事件,要求程式重繪widget,事件迴圈最宗從事件隊列中揀選這個事件並把他們分發到那個徐奧重畫的widget對象。

  並不是所有paint事件都是視窗系統產生,當你調用update()去強行重畫widget,這個widget會post一個paint事件給自己,這個paint事件被放入隊列,最終被事件迴圈分發。

  而當你等不及事件迴圈時,本來應該調用paintEvent()強制立即重畫,但是實際上不可行因為paintEvent()是受保護的函數,因此Qt提供了一個機制直接sending事件給對象,repaint()就使用了這個機制來進行立即重畫。(這是update()更新和repaint()更新的區別)。

  posting相對於sending的一個優勢就是給了Qt一個壓縮事件的機會,假如在一個widget上連續調用update()十次,因update()而產生的這十個事件,會被自動地合併成一個單獨的事件,

 

人工合成的事件

  Qt應用程式可以產生他們自己的事件,或是預定義類型,或是自定義類型。這可以通過創建QEvent類或它的子類的實例,並且調用QApplication::postEvent()或QApplication::sendEvent()來實現。

  這兩個函數需要一個QObject* 與一個QEvent作為參數,如果使用postEvent(),要使用new操作符來創建事件對象,如

  QApplication::postEvent(mainWin,new QKeyEvent(QEvent::KeyPress,Key_X,'X',0));

如果使用sendEvent(),應該使用棧來創建事件

  QKeyEvent event(QEvent::KeyPress,Key_X,'X',0);

  QApplication::sendEvent(mainWin,&event);

定製事件類型

  Qt允許創建自己的事件類型,可以作為對象間的一種通訊機制。是因為這個可以是非同步的,函數調用或槽調用總是同步的。另一個好處是可以被過濾

  post一個定製事件:

    const QEvent::Type MyEvent = (QEvent::Type)1234;

    ...

    QApplication::postEvent(obj,new QCustomEvent(MyEvent));

  事件必須是QCustomEvent類型(或子類)的。構造函數的參數是事件的類型,

  為了處理定製事件類型,要重新實現customEvent()函數:

  void MyLineEdit::customEvent(QCustomEvent *event)

  {

    if(event->type() == MyEvent){

      myEvent();

    }else{

      QLineEdit::customEvent(event);

    }

  }

  可以子類化QCustomEvent,加上別的成員,但是需要在customEvent()中轉換QCustomEvent到特有的類型

 

事件的處理與過濾

  Qt的事件可以在五個不同的層次上被處理

  1.重新實現一個特定的事件handler

    QObject與QWidget提供了許多特定的事件handlers,分別對應於不同的事件類型。(如paintEvent()對應paint()事件)

  2.重新實現QObject::event()

    event()函數是所有對象事件的入口,QObject和QWidget中預設的實現是簡單地把事件推入特定的事件handlers。

   3.在QObject上安裝事件過濾器

     事件過濾器是一個對象,它在事件到達指定目標之前接收這些事件。

   4.在aApp上安裝一個事件過濾器

     它會監視程式中發送到所有對象的所有事件

   5.重新實現QApplication::notify()

     Qt的事件迴圈與sendEvent()調用這個函數來分發事件,

 

特定對象的事件處理

  一些事件類型可以被傳遞。這意味著加入目標對象不處理一個事件,Qt會試著尋找另外的事件接收者。用新的目標來調用QApplication::notify()。舉例來講,key事件是傳遞的,假如擁有焦點的Widget不處理特定鍵,Qt會分發相同的事件給父widget,然後是父親的父親,直到最頂層widget。

 

什麼時候該接收事件,什麼時候該忽略

  通過accept()函數和ignore()函數。可被傳遞的事件有一個accept()函數和一個ignore()函數,可以用他們來告訴Qt,你"接收"或是"忽略"這個事件。假如事件handler調用accept(),這個事件將不會再被傳遞。假如事件handler調用ignore(),Qt會試著查找另外的事件接收者。

 

來源:http://www.cnblogs.com/li-hao/archive/2011/11/13/2247662.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 系統可用率 多級緩存 動態分組切換 DB物理隔離 服務分組隔離 跨機房隔離 漏斗模型 DB限流 系統一般可以分為前端應用系統和後端資料庫系統,前端應用系統實施分散式集群部署技術上是... ...
  • MVVM回顧 經過上一篇文章的介紹,相信你對MVVM的設計思想有所瞭解。MVVM的核心思想就是解耦,View與ViewModel應該感受不到彼此的存在。 View只關心怎樣渲染,而ViewModel只關心怎麼處理邏輯,整個架構由數據進行驅動。不僅View與ViewModel彼此解耦,ViewMode ...
  • Facebook 在2015.9.15發佈了 React Native for Android,把JavaScript 開發技術擴展到了Android平臺。React Native 讓開發者使用 JavaScript 和 React 編寫應用,利用相同的核心代碼就可以創建 基於Web,iOS 和 A... ...
  • 什麼是Maven倉庫 在不用Maven的時候,比如說以前我們用Ant構建項目,在項目目錄下,往往會看到一個名為/lib的子目錄,那裡存放著各類第三方依賴jar文件,如 log4j.jar,junit.jar等等。每建立一個項目,你都需要建立這樣的一個/lib目錄,然後複製一對jar文件,這是很明顯的 ...
  • 在面向對象的軟體設計過程中,一切皆抽象成對象,在一個複雜的軟體系統中有成千上萬甚至百萬千萬級的對象,那麼這麼多對象怎麼去有效的管理?怎麼樣去重覆利用?怎麼去科學合理的組合使其能夠融為一體並且可以順利的工作,這是在面向對象設計中著重需要考慮的問題,那麼我們的前輩有沒有給我們留下來一些科學的指導原則來處 ...
  • 單例模式 一、定義 定義:確保一個類只有一個實例,並提供一個全局訪問點。 理解:保證一個類只有一個實例的一種實現方法(該方法就是為了降低對象之間的耦合度)。 二、代碼塊 1、舉個慄子,拿多線程為慄子,具體看代碼註釋。上代碼~ 二、總結 1、單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提 ...
  • 為什麼要對接改造? 我們公司是做增值稅管理系統的,增值稅系統涉及到開發票的業務,需要與不同的供應商對接開票介面,供應商提供的開票介面,包括四種:A1供應商有兩種,第一種是開票伺服器,第二種是稅盒 A2供應商也是一種是開票伺服器,一種稅盒。 客戶有用稅盒開票的,也有用開票伺服器的,各種情況都有 我們的 ...
  • Redis是業界普遍應用的緩存組件,研究一個組件框架,最直觀的辦法就是從應用方的角度出發,將每個步驟的考慮一番,從這些步驟入手去研究往往能夠最快的體會到一個組件框架的設計哲學。以Redis為例,每當發起一條請求時,redis是如何管理管理網路請求,收到請求後又是通過什麼樣的數據結構進行組織並操作記憶體... ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...