## **架构总览**[[原文链接](https://kivy.org/docs/guide/architecture.html)]
[TOC]
我们想花点时间来解释我们从软件工程的角度来设计Kivy。这是理解一切工作在一起的关键。如果你只是看代码,你可能会有一个粗略的想法,但是由于这种方法对大多数用户来说肯定是令人生畏的,所以本节将更详细地说明实现的基本思路。你可以跳过这个部分,稍后参考一下,但是我们建议至少对它进行粗略的概述。
Kivy由几个建筑块组成,我们将尽快解释。这是架构的图形总结:
![](https://box.kancloud.cn/0bc603897ad47532d67a98643b98e8ea_674x598.png)
### **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)所描述的屏幕上的矩形区域