## **架構總覽**[[原文鏈接](https://kivy.org/docs/guide/architecture.html)]
[TOC]
我們想花點時間來解釋我們從軟件工程的角度來設計Kivy。這是理解一切工作在一起的關鍵。如果你只是看代碼,你可能會有一個粗略的想法,但是由于這種方法對大多數用戶來說肯定是令人生畏的,所以本節將更詳細地說明實現的基本思路。你可以跳過這個部分,稍后參考一下,但是我們建議至少對它進行粗略的概述。
Kivy由幾個建筑塊組成,我們將盡快解釋。這是架構的圖形總結:

### **Core Providers and Input Providers**
***
理解Kivy內部關鍵的一個想法是模塊化和抽象化。我們嘗試抽象開窗口,顯示圖像和文本,播放音頻,從相機獲取圖像,拼寫糾正等基本任務。我們稱這些核心任務。這使得API既易于使用又易于擴展。最重要的是,它允許我們使用我們所謂的特定提供商來為您的應用程序運行的各個方案。例如,在OSX,Linux和Windows上,不同的核心任務有不同的本機API。一種使用這些特定API之一的代碼與一方的操作系統和另一方面的Kivy進行通信(作為中間通信層)是我們所謂的核心提供商。為每個平臺使用專門的核心提供商的優勢是,我們可以充分利用操作系統暴露的功能并盡可能高效地運行。它也給用戶一個選擇。此外,通過使用任何一個平臺附帶的庫,我們有效地減少了Kivy分布的大小,并使包裝變得更容易。這也使得將Kivy移植到其他平臺變得更加容易。 Android端口受益匪淺。
我們遵循與輸入處理相同的概念。輸入提供程序是一段代碼,增加了對特定輸入設備的支持,如Apple的跟蹤器,TUIO或鼠標模擬器。如果您需要添加對新輸入設備的支持,您可以簡單地提供一個新的類,從您的設備讀取輸入數據并將其轉換為Kivy基本事件。
### **繪圖**
***
Kivy的圖形API是我們對OpenGL的抽象。在最低級,Kivy使用OpenGL發布硬件加速繪圖命令。然而,編寫OpenGL代碼可能會有點混亂,特別是對新手來說。這就是為什么我們提供圖形API,讓您可以使用OpenGL(例如畫布,矩形等)中不存在的簡單隱喻繪制東西。
我們所有的小部件都使用這個圖形API,由于性能原因,它在C級上實現。
當然,如果您愿意,還可以使用原始的OpenGL命令。我們的目標版本是所有設備上的OpenGL 2.0 ES(GLES2),所以如果您想保持跨平臺兼容,建議您僅使用GLES2功能。
### **核心**
***
核心包中的代碼提供了常用的功能,如:
**Clock**
您可以使用時鐘來安排計時器事件。支持單次定時器和定時器。
**Cache**
如果你需要緩存你經常使用的東西,你可以使用我們的類而不是編寫你自己的類。
** Gesture Detection**
我們運送一個簡單的手勢識別器,您可以使用它來檢測各種筆畫,如圓形或矩形。你可以訓練它來檢測你自己的筆畫。
**Kivy Language**
kivy語言用于輕松高效地描述用戶界面。
**Properties**
這些不是您可能從python知道的常規屬性。它們是我們自己的屬性類,將您的窗口小部件代碼與用戶界面描述相關聯。
### **UIX (Widgets (小工具)& Layouts(布局))**
***
UIX模塊包含常用的小部件和布局,您可以重新使用它們來快速創建用戶界面。
**Widgets**
小工具是您添加到程序中以提供某種功能的用戶界面元素。它們可能或可能不可見。示例將是文件瀏覽器,按鈕,滑塊,列表等。小工具接收MotionEvents。
**Layouts**
您可以使用布局來排列小部件。當然可以自己計算你的小部件的位置,但是通常使用我們現成的布局更方便。示例是Grid Layouts或Box Layouts。您也可以嵌套布局。
### **模塊**
***
如果您曾經使用過現代的網絡瀏覽器,并使用一些附加組件進行了定制,那么您已經知道了模塊類的基本思想。模塊可用于將功能注入Kivy程序,即使原始作者沒有包含它。
一個例子是一個總是顯示當前應用程序的FPS的模塊,以及一些描繪FPS的圖形。
您也可以編寫自己的模塊。
### **輸入事件(觸摸)[Input Events (Touches)]**
***
Kivy提取不同的輸入類型和來源,如觸摸,鼠標,TUIO或類似的。所有這些輸入類型的共同之處在于,您可以將2D屏幕位置與任何單獨的輸入事件相關聯。 (還有其他輸入設備,例如加速度計,您不能輕易找到2D位置,例如您的設備的傾斜度,這種輸入是單獨處理的,下面我們將介紹以前的類型。)
所有這些輸入類型都由Touch()類的實例表示。 (請注意,這不僅指的是手指觸摸,還包括所有其他輸入類型,為了簡單起見,我們稱之為Touch,它考慮到觸摸用戶界面或屏幕的內容)。觸摸實例或對象可以是三種狀態之一。當觸摸進入這些狀態之一時,您的程序被通知事件發生。觸摸的三個狀態是:
**Down**
觸摸只是一次,在它第一次出現的時刻。
**Move**
觸摸可以在這種狀態下潛在的無限時間。觸摸在其一生中不必處于這種狀態。每當觸摸的2D位置改變時,就會發生“移動”。
**Up**
觸摸最多一次,或永遠不會。實際上,你幾乎總是會收到一個up事件,因為沒有人會永遠在屏幕上握住一根手指,但不能保證。如果您知道用戶將要使用的輸入源,您將知道是否可以依賴此狀態輸入。
### **小工具和事件調度**
***
術語窗口小部件通常用于GUI編程環境中以描述用戶與之交互的程序的某些部分。在Kivy中,小部件是接收輸入事件的對象。它不一定必須在屏幕上有可見的表示。所有小部件都安排在小部件樹(它是從計算機科學類中已知的樹狀數據結構):一個小部件可以有任何數量的子小部件或無。在樹的頂部只有一個根小部件沒有父窗口小部件,所有其他小部件都直接或間接地是這個小部件的子節點(這就是為什么它被稱為根)。
當新的輸入數據可用時,Kivy每次觸發一個事件。小部件樹的根小部件首先接收事件。根據觸摸的狀態,將on_touch_down,on_touch_move或on_touch_up事件(作為參數的觸摸)分派到根窗口小部件,這將導致根窗口小部件對應的on_touch_down,on_touch_move或on_touch_up事件處理程序被調用。
樹中的每個小部件(包括根小部件)都可以選擇消化或傳遞事件。如果事件處理程序返回True,則表示事件已被消化并正確處理。該事件不會進一步處理。否則,事件處理程序通過調用其超類的相應事件處理程序的實現將小部件傳遞給其自己的子進程。這一直到基本的Widget類,在其觸摸事件處理程序中,只會將其觸動傳遞給其孩子:
~~~
# 這類似于移動/向上:
def on_touch_down(self, touch):
for child in self.children[:]:
if child.dispatch('on_touch_down', touch):
return True
~~~
這真的比起來容易得多。以下部分將介紹如何快速創建好應用程序的示例。
通常,您將要限制窗口小部件觀看觸摸屏幕的區域。您可以使用小部件的collide_point()方法來實現此目的。您只需傳遞觸摸的位置,如果觸摸位于“監視區域”內,則返回True,否則返回False。默認情況下,這將檢查窗口小部件的位置(位置; x)所描述的屏幕上的矩形區域