1. 程式人生 > >Kivy A to Z -- Kivy的訊息處理機制

Kivy A to Z -- Kivy的訊息處理機制

外面一直在下雨,比較無聊,順便總結了下Kivy的訊息的處理過程。

總的來說,在Kivy裡,處理的訊息一共有四種:按鍵訊息,滑鼠訊息,觸屏訊息,還有自定義訊息。下面來看下整個訊息的處理流程。

先來看張圖:

 

   先來解釋下這幾個類都是幹嘛的:

1、EventDispatcher:看名稱就知道這是一個訊息分發類,在這個類中通過了以下的主要方法:

register_event_type : 註冊一種訊息型別

bind                :將一個方法繫結到一個訊息型別,用於儲存方法的是一個list型別。

dispatch            :呼叫相應的已經註冊到指定訊息型別的方法。

2、WindowBase:Window的基類,定義了Window的一些常用的方法,如add_wdiget,on_draw。

WindowPygame,WindowX11,WindowSDL這三個類是WindowBase的子類,在某一平臺上只會初始化一種,並且只有一個例項,主要用於接收訊息和處理訊息。具體的初始化程式碼在kivy/core/__init__.py

      #: Instance of a :class:`WindowBase` implementation

Window = core_select_lib('window', (

    ('egl_rpi', 'window_egl_rpi', 'WindowEglRpi'),

    ('pygame', 'window_pygame', 'WindowPygame'),

    ('sdl', 'window_sdl', 'WindowSDL'),

    ('x11', 'window_x11', 'WindowX11'),



), True)


如果沒有特別指定,Kivy將會例項化WindowPygame,作為Kivy的主視窗。所有的畫圖,建立widget的操作都將在這個主視窗上進行。

再來解釋下主要變數和方法。EventDispatcher.__event_stack,這是一個用於儲存所有已經註冊的訊息。新增一個訊息到__event_stack有兩種方法:

1、一種是通過呼叫EventDispatcher.register_event_type

2、另一種方法是在子類中宣告一個類變數__events__,如在WindowBase中就有關於__events__的宣告:

            __events__ = ('on_draw', 'on_flip', 'on_rotate', 'on_resize', 'on_close',

                  'on_motion', 'on_touch_down', 'on_touch_move', 'on_touch_up',

                  'on_mouse_down', 'on_mouse_move', 'on_mouse_up',

                  'on_keyboard', 'on_key_down', 'on_key_up', 'on_dropfile')

並在EventDispatcher.__cinit__時把這些事件型別加到__event_stack變數中。

有了事件的型別,接下來要做的事就是通過EventDispatcher.bind新增事件的處理方法:

例如,在input/providers/mouse.py的MouseMotionEventProvider中,就有下面的bind程式碼:

    def start(self):

        '''Start the mouse provider'''

        if not EventLoop.window:

            return

        EventLoop.window.bind(

            on_mouse_move=self.on_mouse_motion,

            on_mouse_down=self.on_mouse_press,

            on_mouse_up=self.on_mouse_release)

好,註冊了訊息型別和訊息的處理過程,按下來就要等訊息上門了。

前面講到,Kivy例項化了WindowPygame作為主視窗,並且通過呼叫App.run最終進入WindowPygame._mainloop這個訊息迴圈方法。接下來看下_mainloop都做了些什麼:

 

   def _mainloop(self):
        EventLoop.idle()
        for event in pygame.event.get():
            # kill application (SIG_TERM)
            if event.type == pygame.QUIT:
                EventLoop.quit = True
                self.close()
            # mouse move
            elif event.type == pygame.MOUSEMOTION:
                x, y = event.pos
                self.mouse_pos = x, self.system_size[1] - y
                # don't dispatch motion if no button are pressed
                if event.buttons == (0, 0, 0):
                    continue
                self._mouse_x = x
                self._mouse_y = y
                self._mouse_meta = self.modifiers
                self.dispatch('on_mouse_move', x, y, self.modifiers)

            # mouse action
            elif event.type in (pygame.MOUSEBUTTONDOWN,
                                pygame.MOUSEBUTTONUP):
                self._pygame_update_modifiers()
                x, y = event.pos
                btn = 'left'
                if event.button == 3:
                    btn = 'right'
                elif event.button == 2:
                    btn = 'middle'
                elif event.button == 4:
                    btn = 'scrolldown'
                elif event.button == 5:
                    btn = 'scrollup'
                elif event.button == 6:
                    btn = 'scrollright'
                elif event.button == 7:
                    btn = 'scrollleft'
                eventname = 'on_mouse_down'
                if event.type == pygame.MOUSEBUTTONUP:
                    eventname = 'on_mouse_up'
                self._mouse_x = x
                self._mouse_y = y
                self._mouse_meta = self.modifiers
                self._mouse_btn = btn
                self._mouse_down = eventname == 'on_mouse_down'
                self.dispatch(eventname, x, y, btn, self.modifiers)

            # keyboard action
            elif event.type in (pygame.KEYDOWN, pygame.KEYUP):
                self._pygame_update_modifiers(event.mod)
                # atm, don't handle keyup
                if event.type == pygame.KEYUP:
                    self.dispatch('on_key_up', event.key,
                                  event.scancode)
                    continue
                # don't dispatch more key if down event is accepted
                if self.dispatch('on_key_down', event.key,
                                 event.scancode, event.unicode,
                                 self.modifiers):
                    continue
                self.dispatch('on_keyboard', event.key,
                              event.scancode, event.unicode,
                              self.modifiers)
            # video resize
            elif event.type == pygame.VIDEORESIZE:
                self._size = event.size
                self.update_viewport()
 
            elif event.type == pygame.VIDEOEXPOSE:
                self.canvas.ask_update()
            # ignored event
            elif event.type == pygame.ACTIVEEVENT:
                pass
            # drop file (pygame patch needed)
            elif event.type == pygame.USEREVENT and \
                    hasattr(pygame, 'USEREVENT_DROPFILE') and \
                    event.code == pygame.USEREVENT_DROPFILE:
                self.dispatch('on_dropfile', event.filename)
            '''
            # unhandled event !

            else:

                Logger.debug('WinPygame: Unhandled event %s' % str(event))


在這個訊息迴圈裡,通過pygame.event.get()獲取訊息,訊息的型別有:按鍵,滑鼠,這兩種,通過dispatch將訊息傳送到相應的方法中去處理,這裡有一個疑問:怎麼沒有看到Kivy對觸屏訊息的處理?答案是觸屏訊息的處理是在函式開始的EventLoop.idle()裡進行的。這篇講的就要是訊息的處理機制,所以這裡就不再展來。其內容留著以後再講。

相關推薦

Kivy A to Z -- Kivy訊息處理機制

外面一直在下雨,比較無聊,順便總結了下Kivy的訊息的處理過程。 總的來說,在Kivy裡,處理的訊息一共有四種:按鍵訊息,滑鼠訊息,觸屏訊息,還有自定義訊息。下面來看下整個訊息的處理流程。 先來看張圖:      先來解釋下這幾個類都是幹嘛的: 1、EventDis

Kivy A to Z -- Kivy的執行機制

 1. 當看到一個在Android平臺上執行的Python程式時,我的第一個好奇的地方就是它究竟是怎麼做到的。 2. 好,費話少說,我們通過原始碼來分析一下。 3. 首先從dist/default匯入工程,如圖所示: 4. 接下來我們來理順一下整個的Python程式的

Kivy a to z -- Kivy的編譯過程-distribute.sh指令碼分析

1 這一節重點來分析一下distribute.sh,以此來了解一下Kivy的整個編譯過程 2 在上一篇文章中,我們講到編譯的方法: ./distribute.sh -m 'openssl pyjnius pil kivy' 3 那整個過程是怎麼進行的,下面來分析一下: 4 

詳解 Handler 訊息處理機制(附自整理超全 Q&A

Android 為什麼要用訊息處理機制 如果有多個執行緒更新 UI,並且沒有加鎖處理,會導致介面更新的錯亂,而如果每個更新操作都進行加鎖處理,那麼必然會造成效能的下降。所以在 Android 開發中,為了使 UI 操作是執行緒安全的,規定只許主執行緒即 UI 執行緒可以更新 UI 元件。但實際開發中,常常會遇

android 非同步訊息處理機制 — AHandler

1. 引入 ALooper、AHandler、AMessage 在 android multimedia stagefright 的框架程式碼中,通篇都是這幾個類的身影,所以熟悉 android 多媒體框架的第一步必須理解這幾個類的含義。 這幾個類是為了實現非同步訊息機制而設計的

Android非同步訊息處理機制詳解及原始碼分析

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober 轉載煩請註明出處,尊重分享成果】 最近相對來說比較閒,加上養病,所

Android之訊息處理機制(二)Handler的本質-Message和Looper到底是什麼?

目錄 Android之訊息處理機制(二) 以下皆為乾貨,比較幹,需要讀者細細理解。  前面(一)已經解釋了Handler的基本機制了,下面來概括一下本質。 一、MessageQueue        MessageQueue其實就

C# 訊息處理機制及自定義過濾方式

一、訊息概述 Windows 下應用程式的執行是通過訊息驅動的。訊息是整個應用程式的工作引擎,我們需要理解掌握我們使用的程式語言是如何封裝訊息的原理。1. 什麼是訊息(Message) 訊息就是通知和命令。在.NET框架類庫中的System.Windows.Forms名稱

Android非同步訊息處理機制:Looper、Handler、Message

1 簡介 Handler,Looper,Message這三者都與Android非同步訊息處理執行緒相關, Looper:負責建立一個MessageQueue,然後進入一個無限迴圈體不斷從該MessageQueue中讀取訊息; Handler:訊息建立者,一個或者多個

ActiveMQ(二)——訊息處理機制

一、前言 上文中,小編提到安裝ActiveMQ,但是對於ActiveMQ中訊息是用什麼樣的形式儲存的?下面小編就向大家介紹一下。 二、訊息型別 對於訊息的傳遞有兩種型別: 1.點對點的,即一個生產者和一個消費者一一對應; 2.釋出/訂閱模式,即一個生產者產生訊

淺談Android的訊息處理機制--Handler

1.為什麼有Handler? 在UI執行緒中不能進行耗時操作,例如資料讀寫、網路請求、圖片載入等,所以這些操作被放在子執行緒裡,Handler便是子執行緒和UI執行緒之間通訊的橋樑之一。 2.幹什麼用的? 進行非同步訊息處理,即上述內容。 3.Handler類裡面有什麼是必須知道

android的訊息處理機制——Looper,Handler,Message (原理圖、原始碼)

轉自:http://my.oschina.net/u/1391648/blog/282892 在開始討論android的訊息處理機制前,先來談談一些基本相關的術語。   通訊的同步(Synchronous):指向客戶端傳送請求後,必須要在服務端有迴應後客戶端才繼續傳送

Android Handler 非同步訊息處理機制的妙用 建立強大的圖片載入類

                最近建立了一個群,方便大家交流,群號:55032675上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後,提出可以把非同步訊息處理

【Android 開發】: Android 訊息處理機制之四: Android 訊息迴圈 Looper 及其原始碼解析

  上一講我們學習Handler和Message的一些使用方式,我們知道Handler它會發送訊息和處理訊息,並且關聯一個子執行緒,如何傳送訊息入隊和出隊處理訊息等這些都是交給Looper去管理分發的,也就是它是負責整個訊息佇列運轉的一個類,這一講我們就來學習一下Andr

Android的訊息處理機制:Message、Handlerhe和Looper原始碼解析

android的訊息處理有三個核心類:Looper,Handler和Message。其實還有一個Message Queue(訊息佇列),但是MQ被封裝到Looper裡面了,我們不會直接與MQ打交道,因此我沒將其作為核心類。下面一一介紹: 執行緒的魔法師 Looper Loo

圖文解析Android 訊息處理機制

之前也看過不少的書或部落格介紹Android 訊息處理機制的知識點,但總是剛看完感覺懂了,過幾天就忘,今天一邊看原始碼,一邊畫了類圖和時序圖,希望可以加深自己的理解。 Android應用啟動時會

Android中的非同步訊息處理機制

這也是Android中老生常談的一個話題了,它本身並不是很複雜,可是面試官比較喜歡問。本文就從原始碼再簡單的理一下這個機制。也可以說是理一下Handler、Looper、MessageQueue之間的關係。 單執行緒中的訊息處理機制的實現 首先我們以Looper.java原始碼中給出的一個例子來

【Android 開發】: Android 訊息處理機制之三: Handler 中 sendMessage() 原始碼剖析

  閱讀此文,請先閱讀以下相關連線: sendMessage()的幾種過載方法的使用方式的不同以及它們的原始碼的剖析.   通過前面幾講的內容,我們知道Android不但可以使用非同步任務處理多執行

Android架構分析之Android訊息處理機制(二)

作者:劉昊昱  Android版本:4.4.2 在上一篇文章中我們看了一個使用Handler處理Message訊息的例子,本文我們來分析一下其背後隱藏的Android訊息處理機制。 我們可能比較熟悉Windows作業系統的訊息處理模型: while(GetMessage

解析非同步訊息處理機制

 Android 中的非同步訊息處理主要有四部分組成:Meeage、Handler、MessageQueue 和 Looper。其中Meeage 是執行緒之間傳遞的訊息,它可以攜帶少量的資訊,用於在不同執行緒之間交換資料。Handler是傳送和處理訊息的。傳送訊息一般是使用