歡迎您光臨本站 登入註冊首頁

QT/Embedded 窗體事件是如何派發的

admin @ 2014-03-25 , reply:0

概述

   QT的窗體系統可以包含多個進程,對於Linux上的應用,一個進程可以對應一個應用程序,每個應用程序都有自己的MainWindow,也可以有自己的Widgetstac……

    QT 的窗體系統可以包含多個進程,對於Linux 上的應用,一個進程可以對應一個應用程序,每個應用程序都有自己的MainWindow,也可以有自己的Widget stack.。假設一種情況:同時打開多個應用,並且各個應用之間的Windows 不存在完全覆蓋,當我們用滑鼠點擊某個應用的窗體,這個應用的窗體便會出現在屏幕的最上層。對於了解windows 窗體伺服器的同行來說,理解這個並不難,可能有一個類似於Windows XP X-Windows Sever 的進程負責管理滑鼠、鍵盤、與LCD 顯示的操作。對於智能手機的GUI 我是第一次接觸,非智能手機的窗體管理是比較簡單的,以我以前從事的一個手機平台為例,手機只存在一個dialog Stack, 把這個stack 看成一個Z 坐標,棧底位於坐標原點,顯示一整屏幕完整的畫面就是從棧頂沿Z 坐標向下找到沒有被完全覆蓋的windows 直到整個屏幕數據被完全填充,按鍵事件傳入到ui_task(ui_task 負責初始化其他應用,所有windows event 都由dialogstack 應用負責分發)。回歸正卷,QT 是如何管理窗體的呢?下面詳述。

QApplication 如何取得Mouse Event?
    查看QApplication 的代碼,存在一個GuiSever 類型的應用,GuiServer 類型的應用與其他類型的應用有什麼區別的呢?最大的區別就在於通過qt_init 初始化函數調用QWSServer::startup 這個應用建立了一個窗體伺服器。在QWSServer 的構造函數中:
openDisplay(); //初始化顯示、屏幕參數,打開LCD。
openMouse(); //打開滑鼠設備
openKeyboard(); //打開鍵盤設備
    openMouse() :QWSMouseHandler* h = newMouseHandler(ms)打開滑鼠設備,打開滑鼠設備后,通過QSocketNotifier介面監聽打開的滑鼠設備文件描述符,在QWSMouseHandler構造函數中通過調用setMouseHandler 建立了window Server與滑鼠設備之間的通信即:在QWSServer中 connected SIGNAL(mouseChanged)與SLOT(setMouse)(目前這個平台與新的QT開發包有出入,在qt-embedded-free-3.3.6中 滑鼠與windows Server之間通訊是通過在qmouse_ws.cpp中直接調用QWSServer::sendMouseEvent 來實現的)。
    走到這,我們已經能夠獲取滑鼠數據了。這些數據最終會傳遞到哪個窗體,在sendMouseEvent中通過調用window.At(pos)查找windows List所有應用的TOP-LEVEL windows保存在此鏈表中,(TOP-LEVEL窗體是指無parent或者style為:WType_TopLevel的窗體)中請求響應區域包含滑鼠坐標的窗體(requested-region: 窗體顯示的區域),一旦找到數據便會傳遞到此窗體(消息放入到QApplication的incoming消息隊列中,由QApplication負責派發)然後通過Client Socket將此消息傳遞到相應的application的消息隊列里。
 

Windows List是如何建立的?
    我們在創建每一個QWidget 對象時,系統會調用QWidget::create函數,如果我們創建的這個QWidget 為TOP-LEVEL 則將發送消息到QWSSever 在這裡創建一個GlobalWinowsID(參看QWSServer 中get_object_id()調用),如果QWidget 為Child widget 則在這個應用中創建了一個LocaWindowslId,( 參看takeLocalId()) 不管得到的winodwsId 在哪兒被創建,在每個獨立的Application 中都會通過QWidget::setWinId 保存。
    GlobalWindows 與LocalWindows 的區別是:
    在QWSServer 中創建的GlobalwindowsID 用於全局QApp 即:按鍵,滑鼠等事件通過QWSSever 傳遞至相應的應用。按鍵,滑鼠事件則在獲得這些事件的QApp 的Focus Widget 中處理,這些Focus Widget可以是GlobalWindows 也可以是LocalWindows。在這個窗口沒有show 之前,我們還只是得到了WindowsId,當窗口被顯示時,在QWSServer 中將創建一個基於GlobalWindowsID 的QWSWindow 對象並將此對象保存在QWSServer 的windows List 中。

QApplication 中Mouse Event 的傳遞與處理
    當application 的消息隊列不空時調用processEvents 來處理消息隊列。如果應用沒有模式對話框,並且沒有綁定Mouse Event 的widget,則在Application 中遍歷GlobalWindow(對用戶而言是可以滑鼠所在的那個窗體)所對應的Widget 所有子QWidget 對象,也就是說首先從他的child widget 開始查找響應Mouse Event 的Widget,如果這個窗口沒有被優先順序更高的窗口被遮蓋,便會調用raise 函數,將窗體調整到windows list 的最上層。
 

QWSSever 與Application 之間通信管道的建立
    QT 支持多進程,對一個嵌入式設備而言,存在一個獨立的GuiServer 類型的應用,這個應用作為伺服器,其他的應用作為客戶端。伺服器與客戶端的連接在應用初始化的時候完成。
伺服器:
Server Application 進程通過調用QWSServer::startup完成Server 的建立。
客戶端:
Application 調用QWSDisplayData::init 創建QWSSocket 對象並通過connectToLocalFile 建立與伺服器的連接。
歡迎交流。


[admin via 研發互助社區 ] QT/Embedded 窗體事件是如何派發的已經有3561次圍觀

http://cocdig.com/docs/show-post-42108.html