2023年11月11日 星期六

kivy kv language篇 kv language講解

簡述

根據官方解釋

The Kivy language is a language dedicated to describing user interface and interactions. You could compare this language to Qt’s QML (http://qt.nokia.com), but we included new concepts such as rule definitions (which are somewhat akin to what you may know from CSS), templating and so on.

意思是Kivy語言是一種致力於描述用戶界面和交互的語言。您可以將此語言與 Qt 的 QML ( http://qt.nokia.com ) 進行比較,但kv language包含了新概念,例如規則定義(有點類似於CSS )。

因為在官方教學中有許多"我認為"比較不需要的概念,本篇教學將用比較主觀的方式來講解kv language,並只講解我認為重要的部分。

通常在kv file中我們會用以下格式來撰寫kv language

<ClassName>:
    prop1: value1
    prop2: value2
    on_prop: value3

    canvas:
    
        CanvasInstruction1:
            canvasprop1: value1
            
        CanvasInstruction2:
            canvasprop2: value2

    AnotherClassName:
        prop3: value1

上面模板的縮排皆是由4個空格組成

1.版本設定:通常我們會在kv file的最前面設定版本,寫法如下

#: kivy 2.2.0

2.註解:kv language中的註解與python中的註解一樣,都是#號後面加上註解,需要注意的是當註解的#號後面不可"馬上"接:(冒)號

#: this is example

執行結果如下:

(注意:如果多了空格在#號與:號間是可以的)

3.只有根物件需要加角括號

<MyLayout>:

    Button:
        size_hint: .3,.3
        text: 'A1'

    Label:
        text: 'Hello World'

4.kv file中,屬性與event必須在添加的widget前面,否則出錯

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout


class MyLayout(RelativeLayout):
    pass


class Myapp(App):

    def build(self):
        return MyLayout()


if __name__ == '__main__':
    Myapp().run()

在my.kv中寫上此段程式碼:(錯誤寫法)

<MyLayout>:

    Button:
        size_hint: .3,.3
        text: 'A1'

    Label:
        text: 'Hello World'
        
    pos: 100,100
    

執行結果如下:

在my.kv中寫上此段程式碼:(正確寫法)

<MyLayout>:
    pos: 100,100
    
    Button:
        size_hint: .3,.3
        text: 'A1'

    Label:
        text: 'Hello World'
    

執行結果如下:

5.在kv language中

(1)self:代表物件本身

(2)root:代表根物件

(3)app:代表app物件

<MyLayout>:
    pos: 100,100

    Button:
        size_hint: .3,.3
        text: 'A1'
        on_press:
            print(self)
            print(root)
            print(app)

    Label:
        text: 'Hello World'

執行結果如下:

(4)args:還不知道

6.id可以為部件取名,以便調用此部件,不同根物件的部件的id不可互相調用,在python中會這樣寫state= widget.ids["btn1"].state

<A1>:
    prop1: value1

    AnotherClassName:
        id: C3
        prop3: value1
        
<B2>:
    prop1: value1

    AnotherClassName:
        id: D4
        prop3: value1

在以上的程式碼中,A1根物件內可以藉由C3來調用C3的屬性與方法,但不可調用屬於不同根物件的D4。

7.在ki file中if敘述可以用以下格式撰寫

Button:
    text: 'Plop world' if self.state == 'normal' else 'Release me!'

若if敘述過於複雜(就是無法一行結束),我"非常"建議將條件敘述放在main.py中定義,再讓kv file呼叫

7.可以利用id將main.py中的kivy屬性與kv file中同一個根物件的部件串聯起來,以便kv file中的部件在main.py中操作(以下利用Kivy property篇 ObjectProperty類 講解中的例子做示範)

from kivy.app import App
from kivy.uix.gridlayout  import GridLayout
from kivy.properties import ObjectProperty
from kivy.uix.image import Image


class MyLayout(GridLayout):

    #宣告a1為None的ObjectProperty
    a1 = ObjectProperty(None)
    
    #宣告a2為Image的ObjectProperty
    a2 = ObjectProperty(Image(source='dog.jpg'))

    def btn1(self):
        self.a1.add_widget(self.a2)

    def on_a1(self,instance,x):
        print('a1 add dog picture')


class Myapp(App):

    def build(self):
        return MyLayout()


if __name__ == '__main__':
    Myapp().run()

在以上程式碼中,我在MyLayout中宣告a1為ObjectProperty類,其值為None(ObjectProperty會宣告值為None大部分是用來與kv file中的id做連結),宣告a2為ObjectProperty類,其值為Image(source='dog.jpg'),並宣告btn1方法,當btn1方法被呼叫時,a1呼叫add_widget方法將a2加入,最後,當a1發生改變時,自動呼叫on_a1方法,列印'a1 add dog picture'

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    id:b1
    a1:b1

    Label:
        text:'dog'

    Button:
        text: 'A1'
        size_hint: 0.3,0.3
        on_press: root.btn1()

8.在kv file中導入模組與類別、設置變數,導入其他kv file,請參考https://kivy.org/doc/stable/api-kivy.lang.html#lang-directives,官網寫得很清楚,這邊就不再贅述了。

沒有留言:

張貼留言

精選文章

Kivy UIX篇 widget篇 TabbedPanel類 event篇 講解