編程向?qū)?.4架構(gòu)預(yù)覽
我們將要花費一些時間以軟件管理的角度來解釋如何設(shè)計Kivy寂玲。這將是理解每一部分如何一起工作的關(guān)鍵。你也許瀏覽過源代碼梗摇,也許有理一個粗糙的概念拓哟;但是看源代碼也許是令人生畏的,因此這節(jié)內(nèi)容將會詳細(xì)解釋一些基本的概念伶授。你可以略過本節(jié)以待日后再看断序,但我們建議你至少大致瀏覽一下。
Kivy由幾個模塊組成糜烹,下面是Kivy架構(gòu)圖:
一违诗、核心提供者和輸入提供者
理解Kivy內(nèi)部思想的關(guān)鍵是模塊化和抽象。我們試圖抽象一些基本的任務(wù)疮蹦,例如打開一個窗口诸迟、展示圖片和文本、播放音頻挚币、從攝像頭獲取圖像亮蒋、拼寫檢查等等。我們稱它們?yōu)楹诵娜蝿?wù)妆毕。這使得API既容易使用又容易擴展慎玖。更重要的是,它允許我們用:what we call笛粘,在你的應(yīng)用程序運行時的不同場景指定不同的提供者趁怔。例如湿硝,在OS X,Linux和Windows系統(tǒng)上润努,針對不同的核心任務(wù)有不同的本地APIS关斜。一方面這些APIS同操作系統(tǒng)進(jìn)行交流,另一方面我們調(diào)用的Kivy的核心提供者扮演著中間交流層的角色铺浇。使用特殊核心提供者的便利之處是我們可以充分的使用操作系統(tǒng)暴露出來的功能痢畜,盡可能的使程序運行的更高效。它給用戶提供了一個機會鳍侣。另外丁稀,通過使用那些針對一個平臺的庫,我們可以高效地較低應(yīng)用程序打包的尺寸倚聚。這也使得移植到別的平臺更容易些线衫。安卓端口從這方面就獲利巨大。
我們利用同樣的思路處理輸入提供者惑折。輸入提供者授账,支持一些特殊的輸入設(shè)備,例如蘋果的trackpads,TUIO或者鼠標(biāo)模擬器惨驶。如果你需要添加一個新的輸入設(shè)備白热,你只需要簡單的添加一個新的類來讀取你的輸入數(shù)據(jù)并且將其轉(zhuǎn)換到Kivy的基本事件。
二敞咧、圖形
Kivy的圖像接口是我們對OpenGL的抽象棘捣。在更低的層面,Kivy使用OpenGL來分發(fā)硬件加速指令休建。對于一個初學(xué)者來說乍恐,寫OpenGL代碼也許是令人迷惑的。這也是我們提供圖形API接口的原因测砂,你只需要使用簡單的封裝好的方法(例如Canvas茵烈,Rectangle等等)進(jìn)行繪畫即可。
我們的所有部件本身就是使用這些圖形接口砌些,為了更高效的表現(xiàn)呜投,它們在C語言執(zhí)行。
另外一個便利之處是這些圖形接口可以自動優(yōu)化繪畫指令存璃。如果你不是一個OpenGL的專家仑荐,這將是很有用的幫助。在很多的場景下纵东,它將使你的繪畫代碼更高效粘招。
當(dāng)然你也可以使用OpenGL命令。我們在所有的設(shè)備上使用的是OpenGL2.0(GLSE2)偎球,所以如果你想保持更好的跨平臺的兼容性洒扎,我們建議你僅僅使用GLSE2提供的函數(shù)辑甜。
三、核心
核心提供者提供了一些通用的功能袍冷,例如:
- Clock(時鐘):你可以使用時鐘來計劃定時器事件磷醋。一次性的定時器和周期性的定時器都被支持。
- Cache(緩存):如果你需要將你常用的一些東西緩存起來胡诗,你可以使用我們提供的緩存類邓线,而不是自己再造一個輪子。
- Gesture Detection(手勢檢測):我們提供了一個簡單的手勢識別乃戈,你可以用來檢測不同類型的軌跡褂痰,例如圓圈或者矩形。你可以自己訓(xùn)練它來檢測自己的軌跡症虑。
- Kivy Language(Kivy語言):Kivy語言可以容易并高效地描述用戶接口。
- Properties(屬性):這里的屬性不是你熟知的Python里面的屬性归薛,它們是我們自己的屬性類谍憔,以用來鏈接你的部件代碼和用戶接口描述。
四主籍、UIX(部件和布局)
UIX模塊包含常用的部件和布局习贫,你可以重復(fù)使用它們來創(chuàng)建一個用戶接口。
- Widgets:部件是用戶接口元素千元,它們有的可見苫昌,有的不可見,例如文件瀏覽窗口幸海、按鈕祟身、滑塊、列表等等物独。部件接收MotionEvents袜硫。
- Layouts:你可以使用布局來排列部件。當(dāng)然你可以手動的自己來布局部件挡篓,但是通常使用布局會更加的方便婉陷。布局包括網(wǎng)格布局、盒子布局等官研,你也可以布局嵌套秽澳。
五、模塊
如果你曾經(jīng)使用過現(xiàn)代的網(wǎng)頁瀏覽器戏羽,并定制過一些插件担神,那么你已經(jīng)了解了關(guān)于我們模塊類的基本概念。模塊用來被注入功能到Kivy程序中蛛壳,即使原作者沒有包括它杏瞻。
一個例子展示了一個總是顯示FPS的模塊和一些描繪FPS的圖表所刀。
你也可以寫自己的模塊。
六捞挥、輸入事件(觸摸)
Kivy抽象了不同的輸入類型和資源浮创,例如觸摸、鼠標(biāo)砌函、TUIO等等斩披。所有這些輸入類型的共同之處是你可以使用一個屏幕上的2D坐標(biāo)以及一些特殊的輸入事件關(guān)聯(lián)起來。(一些其它的輸入設(shè)備讹俊,例如加速器你就不能簡單的使用2D坐標(biāo)來描述垦沉。這類輸入設(shè)備被分別對待)
所有的這些輸入設(shè)備類型被Touch()類的實例來表示。(注意這不僅僅代表手指觸摸仍劈,也同樣表示別的輸入類型厕倍。我們只是因為類似而采取了Touch的名字。)一個Touch的實例或?qū)ο蠓犯恚齻€狀態(tài)讹弯,當(dāng)一個觸摸進(jìn)入到了這些狀態(tài),你的程序被通知这溅,該事件發(fā)生了组民。這三個狀態(tài)如下:
- Down:一個觸摸被按下一次
- Move:A touch can be in this state for a potentially unlimited time. A touch does not have to be in this state during its lifetime. (一個觸摸可能在一個潛在的無限的時間里。一個觸摸在它的生命周期中不會一直在這個狀態(tài)悲靴。)當(dāng)一個觸摸的2D坐標(biāo)發(fā)生改變時臭胜,Move將會事件發(fā)生。
gthank:前面的兩句話不知道什么意思癞尚!
- Up:一個觸摸抬起至多一次或沒有耸三。實際應(yīng)用中,你將總會接收到一個Up事件否纬,因為沒有人會永遠(yuǎn)將一個手指放在屏幕上吕晌,但是這不是有保證的。如果你知道用戶正在使用的輸入源临燃,你將會知道是否依賴這個狀態(tài)睛驳。
七、部件和事件發(fā)送
部件這個術(shù)語通常用在GUI編程中膜廊,來描述和用戶交互的那部分程序乏沸。在Kivy中,一個部件是一個對象由來接收輸入事件爪瓜。在屏幕上有一個可視的代表是沒有必要的蹬跃。所有的部件在一個部件樹中管理:一個部件能有零或者多個子部件。但是在樹的頂端只能有一個根部件铆铆,根部件沒有父部件蝶缀;其它的部件直接或間接的是根部件的子部件丹喻。
當(dāng)一個新的輸入數(shù)據(jù)可用時,Kivy發(fā)送一個事件翁都。根部件首先收到該事件碍论。根據(jù)觸摸的狀態(tài),on_touch_down, on_touch_move, on_touch_up事件被發(fā)送到根部件柄慰,這將導(dǎo)致在根部件中相應(yīng)的事件處理函數(shù)被調(diào)用鳍悠。
在樹中的每一個部件能選擇吸收或傳遞事件。如果一個事件處理函數(shù)返回True坐搔,這意味著這個事件被吸收并正確的處理藏研,對于該事件,沒有進(jìn)一步的處理會發(fā)生概行。否則蠢挡,這個事件處理函數(shù)通過調(diào)用它的父類的各自事件處理函數(shù)的實現(xiàn),傳遞部件到它自己的子部件上凳忙。最終事件傳遞到部件的基類袒哥,在它的事件處理函數(shù)里,什么到不做消略,僅僅傳遞touchs到它的子部件。
#這是一個move/up的模擬
def on_touch_down(self, touch):
for child in self.children[:]:
if(child.dispatch('on_touch_down', touch)):
return True
它可能比看起來更容易瞎抛。下面的章節(jié)會展示一個例子艺演,漂亮的應(yīng)用程序能夠快速的被創(chuàng)建。
通常你想限制一個部件監(jiān)聽觸摸事件的屏幕區(qū)域桐臊。你可以使用部件的collide_point()方法來做到這點胎撤。你傳遞給它觸摸的坐標(biāo),并且它將返回監(jiān)聽的區(qū)域断凶。默認(rèn)情況下伤提,屏幕上矩形區(qū)域的檢測使用部件的坐標(biāo)和尺寸來描述,但是你也能在自己的類中進(jìn)行重載认烁。