วันพุธที่ 30 กันยายน พ.ศ. 2558

Kivy(Screen manager)

  Screen manager ตามชื่อก็คือ ตัวจัดการหน้าจอ ในหัวข้อนี้จะพูดถึงการเลือกสีสำหรับตัวที่เราสร้างขึ้นมาโดยตัวคลาส ScreenManager นั้นจะช่วยให้เราจัดการหน้าจอที่ขนาดต่างกันแต่อยุ่บนหน้าต่างเดียวกันใน Kivy จะให้ความสำคัญกับหน้าจอมากกว่าหน้าต่างที่ใช้ตอนรันโค้ดเพราะต้องเขียนลงไปในหลายอุปกรณ์
  ตัวที่เราสร้างขึ้นมานั้นมีอยู่สีเดียวซึ่งเราจะมีวิธีเปลี่ยนสี โดยใช้ widget ที่เรียกว่า ColorPicker ตัวนี้เป็น widgets ที่ทาง Kivy มีมาให้ซึ่งหน้าตาจะประมาณนี้

(ภาพจากหนังสือ Kivy interacrive application in python)

 จะเห็นได้ว่าตัว widget นั้นมีขนาดออกไปทางแนวกว้างซึ่งมันจะยากที่จะบรรจุลงไปใน interface ที่เราใช้ปกติซึ่งจุดนี้จะมีตัว ScreenManager เข้ามาช่วยแก้ปัญหาโดยมีพื้นฐานหลักง่ายๆเลยคือมันจะยอมให้เราให้ได้หลายหน้าต่างหรือก็คือมันจะเปลี่ยนมาที่หน้าต่างนี้เพื่อให้เราปรับสีโดยให้เราสร้างไฟล์ Kv ขึ้นมาใหม่โดยให้มีคลาส ScreenManager อยู่ด้วย

โค้ดในไฟล์ .kv 

# File name: comicscreenmanager.kv
#:kivy 1.7.0
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
<ComicScreenManager>:
    transition: FadeTransition()
    color_picker: _color_picker#สร้าง Attibute เพื่อนำไปใช้
    ComicCreator:
    Screen:#ไม่ได้เรียกใช้ Colorpicker ตรงๆแต่ว่าฝังเข้ามากับ ScreenWidget แล้วนำไปใช้
        name: 'colorscreen'
        ColorPicker:
            id: _color_picker#คือการนำตัว Attibute มาใช้งานนั้นเอง
            Button:
                text: "Select"
                pos_hint: {'center_x': .75, 'y': .05}
                size_hint: None, None
                size: 150, 50
                on_press: root.current = 'comicscreen'
ตัว ScreenManager นั้นมีควรจะมี widget ของ screen เป็นคลาสหลักไม่สามารถมีพวก Label,Button,layouts ใส่ลงไปได้
และเราต้องทำการแก้ส่วนหัวของไฟล์ comiccreator.kv เพื่อให้สามารถใช้งานในส่วนของ Screen

<ComicCreator@Screen>:
    name: 'comicscreen'

  การที่เราตั้งชื่อเป็นการทำเพื่อระบุว่าเป็น Screen ตัวไหนโดยชื่อนี้นั้นได้ถูกใช้ในส่วนด้านบนตรง Button ไปแล้วซึ่งเราได้ทำการเรียกใช้ฟังก์ชั่น on_press ซึ่ง root.current ตอนนี้ก็คือ ScreenManager นั้นเองพอเรากดลงไปก็จะเรียกตัว comicscreen มาใช้งาน
  ในส่วนต่อไปเราต้องทำการแก้ในส่วนของ generaloption เพื่อให้กด color แล้วเด้งหน้าต่าง colorpicker ออกมาโดยไปทำการเพิ่มฟังก์ชั่นในไฟล์ generaloptions.py 

def color(self, instance):
  self.comic_creator.manager.current = 'colorscreen'

แล้วท้ายสุดในหัวข้อนี้เราต้องทำการไปเพิ่มในไฟล์ comiccreator.py เพื่อให้มันทำการใช้งานออกมาได้นั้นเอง

from kivy.uix.screenmanager import ScreenManager#เพิ่มส่วนของ ScreenManager เข้ามา
class ComicScreenManager(ScreenManager):#สร้างคลาสที่สือทอดตัวScreenManager
    pass
class ComicScreenManagerApp(App):
    def build(self):
        return ComicScreenManager()
#ให้รีเทิร์นตัวมันเองกลับไปเวลาเรียกใช้คลาสนี้โดยส่วนนี้จะไปทำงานในไฟล์ .kv
โดยในส่วนของ python นั้นเราสามารถใช้คำสั่ง Builder String ในการเขียนโค้ดของ Kivy ลงไปได้
ตัวอย่างเช่น

โค้ดตัวอย่าง

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder

Builder.load_string("""
<GridLayout>:
    cols:2
    Label:
        color: 1,0,0,1
        canvas:
            Line:
                points: self.x, self.y, self.x + self.width, self.y + self.height
    Widget:
        canvas:
            Line:
                points: self.x, self.y, self.x +self.width, self.y + self.height
""")

class LabelApp(App):
    def build(self):
        return GridLayout()

if __name__=="__main__":

    LabelApp().run()

จะเห็นว่าก็สามารถรันได้เหมือนพิมไฟล์ .kv เพียงแค่เป็นการโหลดตัว String เข้ามานั่นเองผลลัพท์ที่ได้จากโค้ดด้านบน

(ภาพจากหนังสือ KivyInteractiveinpython)
  และจากผลลัพธ์ที่ได้ด้านบนเราจะสังเกตได้อีกอย่างเราได้ทำการเปลี่ยนสีเป็นสีแเดงในส่วนของ Label แต่ว่าพอเราเรียกในส่วนของ widget(เส้นที่ 2)จะเห็นได้ว่าก็ยังเป็นสีแดงเหมือนกัน
  โดยเมื่อเราต้องการนำไปเรียกใช้เราต้องทำการเพิ่มโค้ดส่งไปในส่วนที่มันใช้วาดรูปขึ้นมาคือในส่วนของ ToolStickman,draw (class ToolFigure )Tool,widgetize (class ToolFigure )

โค้ดที่เพิ่มคือ

screen_manager = self.parent.comic_creator.manager
color_picker = screen_manager.color_picker

โดยโค้ดนี้คือมีการสร้าง Screenmanager ขึ้นเพิ่อเราทำการเลือกสีแล้วให้ตัว color picker เก็บสีที่เราเลือกไว้แล้วให้เราทำการไปเพิ่มส่งในส่วนที่ใช้วาดแต่ละตัว

วันจันทร์ที่ 28 กันยายน พ.ศ. 2558

Kivy(bind and unbinding event)

ในบทนี้เราจะมาเริ่มจากการคลิกเมาส์เพื่อวาดรูปใน DrawingSpace แล้วลากเมาส์แล้วกำหนดขนาดของวงกลมได้เราถึงมาทำเริ่มสร้างส่วนประกอบ Draggablewidget ซึ่งจะทำให้เราสามารถลากมันบน DrawingSpace ได้ โดย Diagram จะช่วยเราในการเข้าใจสืบทอดโครงสร้างจาก toolbox.py




จาก Diagram จะเห็นว่าได้นำ ToolButton กับ ToolStickman จากที่อธิบายในตัวอย่างที่แล้วมาใช้แล้วยังเพิ่มไปอีก 3 class คือ ToolFigure, Toolline, ToolCircle โดย class  ToolFigure นั้นจะมี 6 เมทอด โดยมีโค้ดดังนี้

โค้ดในไฟล์ toolbox.py (classToolFigure)

class ToolFigure(ToolButton):
    def draw(self, ds, x, y):
        (self.ix, self.iy) = (x, y)
        with ds.canvas:
            self.figure = self.create_figure(x, y, x+1, y+1)
        ds.bind(on_touch_move = self.update_figure)
        ds.bind(on_touch_up = self.end_figure)
"""ฟังก์ชั่นนี้จะทำการ override ฟังก์ชั่น draw ของ ToolButton ตำแหน่งที่เรากดลงไปนั่นจะบอกถึงจุดเริ่มต้นของรูปร่างของเราไม่งั้นก็จุดกึ่งกลางของวงกลมหรือจุดสิ้นสุดของเส้น"""
    def update_figure(self, ds, touch):
        if ds.colide_point(touch.x, touch.y):
            (x, y) = ds.to_widget(touch.x, touch.y)
            ds.canvas.remove(self.figure)
            with ds.canvas:
                self.figure = self.create_figure(self.ix, self.iy, x, y)
"""เมทอดนี้จะทำการเพิ่มจุดสิ้นสุดของรูปร่างเมื่อเวลาที่เราทำการลากอย่างไรก็ตามจุดสิ้นสุดของเส้นหรือเรเดียน(ระยะจากจุดเริ่มจนถึงจุดจบ)ของวงกลม"""
    def end_figure(self, ds, touch):
        ds.unbind(on_touch_move = self.update_figure)
        ds.unbind(on_touch_up = self.end_figure)
        ds.canvas.remove(self.figure)
        (fx, fy) = ds.to_widget(touch.x, touch.y)
        self.widgetize(ds, self.ix, self.iy, fx, fy)
"""เมทอดนี้จะบอกถึงจุดจบสุดท้ายของรูปร่างมีวิธีการเหมือนฟังก์ชั่น update_figure เราสามารถใส่ค่าสุดท้ายลงใน DraggableWidget ได้(ดูใน widgetize)"""
    def widgetize(self, ds, ix, iy, fx, fy):
        widget = self.create_widget(ix,iy,fx,fy)
        (ix,iy) = widget.to_local(ix,iy,relative=True)
        (fx,fy) = widget.to_local(fx,fy,relative=True)
        widget.canvas.add( self.create_figure(ix,iy,fx,fy))
        ds.add_widget(widget)
"""เมทอดนี้จะทำการสร้าง DraggableWidget และ วางรูปร่างที่เราสร้างลงไปและใช้ จุดร่วม 4 จุดในการกำหนดค่าให้ถูกต้องโดยการใช้ localization method"""
    def create_figure(self,ix,iy,fx,fy):
        pass
    def create_widget(self,ix,iy,fx,fy):
        pass

แล้วก็เราจะมาทำการเพิ่มเติม class TooLine และ ToolCircle โดยทำการสืบทอดคลาสแม่มาจาก ToolFigure โดยจะเป็นส่วนสุดท้ายใน ไฟล์ toolbox.py โดยมีโค้ดให้คือ

class ToolLine(ToolFigure):
    def create_figure(self, ix, iy, fx, fy):
        return Line(points=[ix, iy, fx, fy])
    def create_widget(self, ix, iy, fx, fy):
        pos = (min(ix, fx), min(iy, fy))
        size = (abs(fx-ix), abs(fy=iy))
        return DraggableWidget(pos = pos, size = size)
class ToolCircle(ToolFigure):
    def create_figure(self, ix, iy, fx, fy):
        return Line(circle = [ix, iy, math.hypot(ix-fx, iy-fy)])
    def create_widget(self, ix, iy, fx, fy):
        r = math.hypot(ix-fx, iy-fy)
        pos = (ix-r, iy-r)
        size = (2*r, 2*r)
        return DraggableWidget(pos = pos , size = size)

 ซึ่งสุดท้ายเราก็ต้องไปแก้ไฟล์ toolbox.kv โดยโค้ดที่เราต้องจัดการแก้คือ

#:import toolbox toolbox
<ToolButton>:
  size_hint: None,None
  size: 48,48
  group: 'tool'
  canvas:
    PushMatrix:
    Translate:
      xy: self.x,self.y
  canvas.after:
    PopMatrix:
<ToolBox@GridLayout>:
  cols: 2
  padding: 2
  tool_circle: _tool_circle
  tool_line: _tool_line
  tool_stickman: _tool_stickman
  ToolCircle:
    id: _tool_circle

    canvas:
      Line:
        circle: 24,24,14
  ToolLine:
    id: _tool_line

    canvas:
      Line:
        points: 10,10,38,38
  ToolStickman:
    id: _tool_stickman

    StickMan:
        pos_hint: {'center_x':.5,'center_y':.5}

เราสามารถ import class เข้ามาได้โดยใช้คำสั่ง #:import Name package.ClassName ในKivy ซึ่งจะมีความหมายเหมือนกับ from package.ClassName import ClasName as Name ใน Python
ในส่วนต่อไปเราจะทำการสร้าง bind event ใน ภาษา Kivy โดยการทำใน Kivy นั้นจะทำการเพิ่ม event เข้าไปในส่วนที่เจาะจงจะแอดเข้าไปได้ง่ายกว่ายกตัวอย่างเช่นเราต้องการเพิ่มการกดเข้าไปใน DragableWidget ส่วนประกอบทั้งหมดที่มีอันนี้ก็จะได้รับการ implement ไปและเราจะมาเริ่มทำการเพิ่ม event เข้าไปใน Button และ ToggleButton โดยก่อนอื่นต้องทำการสร้างไฟล์ generaloption.kv ขึ้นมาใหม่ก่อน

โค้ดในไฟล์ generaloption.kv

#:import generaloptions generaloptions
<GeneralOptions>:
  orientation: 'horizontal'
  padding: 2
  Button:
    text: 'Clear'
    on_press: root.clear(*args)
  Button:
    text: 'Remove'
    on_release: root.remove(*args)
  ToggleButton:
    text: 'Group'
    on_state: root.group(*args)
  Button:
    text: 'Color'
    on_press: root.color(*args)
  ToggleButton:
    text: 'Gestures'
    on_state: root.gestures(*args)

 จะเห็นได้ว่า button มี event เพิ่มมา 2 อันได้แก่ on_press และ on_release โดยรูปแบบการทำงานของมันนั้นคล้ายกับ on_touch_down และ on_touch_up อย่างไรก็ตามในกรณีนี้เราไม่จำเป็นต้องกังวลที่จะเรียกใช้เมทอด collide_point เพราะเราใช้ on_press ที่ clear button และ color button และ on_release ที่ remove button ซึ่งมันจะไม่ชนกันอยู่แล้วและให้เราสร้าง generaloptions.py ขึ้นมา

โค้ดในไฟล์ generaloptions.py คือ

from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty, ListProperty
class GeneralOptions(BoxLayout):
    group_mode = False
    translation = ListProperty(None)
    def clear(self, instance):
        self.drawing_space.clear_widgets()
    def remove(self, instance):
        ds = self.drawing_space
        if len(ds.children) > 0:
            ds.remove_widget(ds.children[0])
    def group(self, instance, value):
        if value == 'down':
            self.group_mode = True
            else:
                self.group_mode = False
                self.unselect_all()
    def color(self, instance):
        pass
    def gestures(self, instance, value):
        pass
    def unselect_all(self):
        for child in self.drawing_space.children:
            child.unselect()
    def on_translation(self,instance,value):
        for child in self.drawing_space.children:
            if child.selected:
                child.translate(*self.translation)

แล้วสุดท้ายเค้าก็จะให้ตัวอย่างโค้ดมาให้สร้างไฟล์ .py ของ ทุกไฟล์แล้วก็เสร็จเรียบร้อยสามารถใช้งานได้

Kivy(MouseDrag& Adding)

หลังจากเราได้ทำการกดแล้วมีกรอบสี่เหลี่ยมขึ้นมาล้อมรอบได้ละนั้นต่อไปที่เราจะทำคือเมื่อเวลากดแล้วเราลากเมาส์นั้นจะทำให้ตัว Stickman นั้น ขยับ ตามเมาส์เราแล้วพอเราปล่อยก็จะให้ตัว Stickman อยู่ตำแหน่งที่เราปล่อยเมาส์เริ่มด้วยต้องทำการเพิ่มเติมฟังก์ชั่นเพิ่มให้มันสามารถลากแล้วขยับได้โดยในหนังสือนั้นจะทำการเพิ่มไปเรื่อยๆแล้วอธิบายเป็นทีละฟังก์ชั่นไปโดยเริ่มจาก

def on_touch_move(self, touch):
        (x,y) = self.parent.to_parent(touch.x, touch.y)
        if self.selected and self.parent.collide_point(x - self.width/2, y - self.height/2):
            self.translate(touch.x-self.ix, touch.y-self.iy)
            return True
        return super(DraggableWidget, self).on_touch_move(touch)

  ในส่วนของฟังก์ชั่นด้านบนนั้นการทำงานของฟังก์ชั่นก็คือการให้แน่ใจว่า ตัว widget Draggable นั่นถูกเลือกอยู่ โดยเราจะใช้คำสั่ง collide_point แต่คราวนี้เราจะใช้ parent(DrawingSpace) แทน self เราต้องทำการตรวจสอบตัว parent ซึ่งก็คือ drawingspace เพราะว่าตัว stickman นั้นสามารถลากได้ใน DrawingSpace ไม่ใช่ DraggableWidget มาถึงฟังก์ชั่นต่อไปคือ

def translate(self, x, y):
        self.center_x = self.ix = self.ix + x
        self.center_y = self.iy = self.iy + y

  ฟังก์ชั่นนี้จะทำให้ย้าย DraggableWidget (x,y) พิกเซลโดยทำการใส่ค่าเข้าไปที่ center_x และ center_y ซึ่งฟังก์ชั่นนี้ดูจะไม่ค่อยจำเป็นเท่าไหร่แต่มันจะช่วยเราสามารถใช้คำสั่ง group ได้ง่ายขึ้น

def on_touch_up(self, touch):
        if self.selected:
            self.unselect()
            return True
        return super(DraggableWidget, self).on_touch_up(touch)

เป็นฟังก์ชั่นเวลาเราปล่อยเมาส์ออกถ้าเราทำการเลือกตัว Stickman อยู่จะเรียกใช้ฟังก์ชั่น unselect

def unselect(self):
        if self.selected:
            self.canvas.remove(self.selected)
            self.selected = None

ฟังก์ชั่นนี้นั้นจะทำการลบคำสั่ง line ออกจากตัว canvas และกำหนดค่าขึ้นมาใหม่โดนกำหนดให้เป็น None
จากฟังก์ชั่นที่เพิ่มมาทั้งหมดเราก็จะทำการลากตัว Stickman ของเราได้แล้วไปยังส่วนต่อไปคือการเพิ่มตัว Stickman
  ก่อนอื่นเราต้องเข้าใจหลักการของ RelativeLayout ก่อนโดยจะมีตัวอย่างจากในรูป

(ภาพจากหนังสือ Kivy interactive application in python)

จากรูปด้านบนนั้นจะเห็นว่ามีหลายสีโดยจะเริ่มจากสีน้ำเงินเป็น parent ของสีเขียว และ สีเขียวเป็น parent ของสีแดง และ layoutสีน้ำเงินเป็นขนาดของหน้าต่างโดยจากรูปเมื่อกี้จะมีมาตรฐานกำหนดไว้ 4 อันที่ class widgets ได้ให้ไว้

  1.to_parent () : เมทอดนี้จะทำการเปลี่ยนรูปแบบจุดร่วมกันของ widgets ที่กำหนดกับตัว parent ยกตัวอย่างเช่น a.parent.to_parent(a.x, a.y) จะรีเทิร์นค่ากลับมาเป็น จุดที่ร่วมกันคือ (50,25)
  2.to_local(): เป็นเมทอดที่เปลี่ยนรูปแบบจุดร่วมกันระหว่างตัว parent ของมันกับ widgets  ปัจจุบันยกตัวอย่าง a.parent.to_local(50,25) จะรีเทิร์นค่ากลับมาเป็นจุดร่วมกันระหว่าง a กับ layout สีแดง
  3.to_window(): เมทอดที่ทำการเปลี่ยนรูปแบบจุดร่วมของ widgets ที่เลือกไปเป็น window ยกตัวอย่าง a.to_window(a.x, a.y) จะรีเทิร์นค่ากลับมาคือ 100, 50
  4.to_widgets(): เมทอดที่ทำการเปลี่ยนรูปแบบจากจุดร่วมไปเป็นตัวอ widgets ที่เลือกยกตัวอย่าง a.to_widget(100, 50) ก็จะ รีเทรินค่ามาเป็น (0, 0) อีกรอบนึงศึ่งเป็นร่วมกันของ layout สีแดง
 อันที่ 3 กับ อันที่ 4 ไม่จำเป็นต้องใช้ parent เพราะตัว Kivy นั้นคิดเอาเองว่า จุดที่ร่วมกันต้อง relative กับ parent เสมอ
 ลองดูจากในตัวอย่างที่ในหนังสือให้มาโดยจะทำการเพิ่ม event เข้าไปใน tool box button โดยต้องทำการสร้างไฟล์ .py ขึ้นมาใหม่ คือ toolbox.py โดยโค้ดคือ

โค้ดในไฟล์ toolbox.py

import math
from kivy.uix.togglebutton import ToggleButton
from kivy.graphics import Line
from comicwidgets import StickMan, DraggableWidget

class ToolButton(ToggleButton):
    def on_touch_down(self, touch):
        ds = self.parent.drawing_space
        if self.state == 'down' and ds.collide_point(touch.x, touch.y):
            (x, y) = ds.to_widget(touch.x, touch.y)
            self.draw(ds, x, y)
            return True
            return super(ToolButton, self).on_touch_down(touch)
    def draw(self, ds, x, y):
        pass


จะเห็นได้ว่าตรงส่วนเงี่อนไขคือส่วนที่ตรวจสอบว่าตัว event นั้นเกิดอยู่ในส่วนของ drawingspace
และจะมีโค้ดมาเพิ่มต่อคือ

class ToolStickman(ToolButton):
    def draw(self, ds, x, y):
        sm = StickMan(width=48, height=48)
        sm.center = (x, y)
        ds.add_widget(sm)


เราได้สร้างส่วนประกอบของตัว Stickman แล้วก็ได้ทำการใส่ค่าให้ center ด้วยวิธีการ translate จุดร่วมมาถึงจุดนี้เราได้ทำการ add ตัว Stickman เข้าไปนจุดร่วมเรียบร้อยแล้ว

วันพุธที่ 23 กันยายน พ.ศ. 2558

Kivy(WidgetsEvent)

  ในเรื่องนี้จะอธิบายเกี่ยวกับการสร้างการทำงานให้มีการตอบโต้กับเราโดยทีการเกิดนั้นจะมาจากการจัดการ canvas ของ widgets ตัวนึงกับด้วย widgets ของอีกตัวนึงเริ่มจากให้เราลองดูตัวอย่างในท้ายบทที่ 1(ComicCreator) โดยในบทที่ 1 นั้นแต่ละตัวจะไม่สามารถกดแล้วมีการตอบสนองใดๆได้แต่ในบทนี้นั้นเราจะทำให้มันตอบโต้กับเราได้โดยมี diagram แสดงว่าตัวไหนสัมพันธ์กับตัวไหนจากรูป


ภาพจากหนังสือ kivy interactive applications in Python
 โดยส่วนสำคัญที่เราใช้อ้างอิงว่าเป็นตัวไหนนั้นคือ id ซึ่งจะกำหนดไว้ใน .kv หรือ ส่วนของ kivy นั้นเอง
และจะมีตัวอย่างโค้ดที่ให้มาคือโค้ดเดียวกับตอนท้ายบทที่1แต่มีการเพิ่ม attibute ของแต่ละตัวเข้าไป

โค้ดในไฟล์ .kv
<ComicCreator>:
  AnchorLayout:
    anchor_x: 'left'
    anchor_y: 'top'
    ToolBox:
      id: _tool_box
      drawing_space: _drawing_space
      comic_creator: root

      size_hint: None, None
      width: 100
  AnchorLayout:
    anchor_x: 'right'
    anchor_y: 'top'
    DrawingSpace:
      id: _drawing_space
      status_bar: _status_bar
      general_option: _general_options
      tool_box: _tool_box

      size_hint: None,None
      width: root.width - _tool_box.width
      height: root.height -_general_options.height-_status_bar.height
  AnchorLayout:
    anchor_x: 'center'
    anchor_y: 'bottom'
    BoxLayout:
      orientation: 'vertical'
      GeneralOptions:
        id: _general_options
        drawing_space: _drawing_space
        comic_creator:root

        size_hint: 1,None
        height: 48
      StatusBar:
        id: _status_bar
        size_hint: 1,None
        height: 24
 ชื่อของ attibute และ ชื่อ id นั้นจะไม่แตกต่างกันจาก โค้ดที่เป็นตัวอย่างท้ายบทก่อนหน้านี้แต่ว่าจะมีการเติม _ จากชื่อของ attibute เพื่อให้รู้ว่าใช้งานใน Kivy แต่ที่ไม่มี _นำหน้าจะใช้งานเป็น attibute ใน python
 พอเราทำการแก้ไขโค้ดที่ใช้งานเสร็จแล้วต่อจากนี้ก็จะทำการเริ่มสร้าง events แบบพื้นฐานคือการสร้าง stickman ขึ้นมาโดยให้มันสามารถลากไปมาได้โดยจะมีวิธีคิดคือให้เรากดเมาส์แล้วจึงสามารถลากได้แล้วทำการปล่อยเมาส์เราจะไม่สามารถลากไปมาได้โดยจะมีตัวอย่างโค้ดมาให้ลองแก้จากไฟล์ comicwidgets.kv ของท้ายบทที่แล้วโดยการเพิ่มเข้าไปที่ส่วนหัวคือ

โค้ดในไฟล์ .kv

#:import comicwidgets comicwidgets
<DraggableWidget>:
  size_hint:None, None

<StickMan>:
  size: 48,48
  ... 


ตอนนี้เราจะมี widgets ตัวใหม่ขึ้นมาเรียกว่า Draggablewidgets โดยจะให้มันเอาค่า size_hintเป็น None เพื่อให้เราทำให้ค่าตัว stickman ของเราตายตัวแล้วเราจะทำการเพิ่มไฟล์ .py เพื่อให้มันเป็นส่วนคำนวณโดยมีโค้ดมาให้ลองคือ

โค้ดในไฟล์ .py

#filename comicwidgets.py
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Line

class DraggableWidget(RelativeLayout):
    def __init__(self, **kwargs):
        self.selected = None
        super(DraggableWidget, self).__init__(**kwargs)
    def on_touch_down(self, touch):
        if self.collide_point(touch.x, touch.y):
            self.select()
            return True
        return super(DraggableWidget, self).on_touch_down(touch)
    def select(self):
        if not self.selected:
            self.ix = self.center_x
            self.iy = self.center_y
            with self.canvas:
                self.selected = Line(rectangle =(0,0,self.
width,self.height) , dash_offset = 2)
class StickMan(DraggableWidget):
    pass

จากโค้ดทางด้านบนจะทำให้เราได้กรอบ 4 เหลี่ยมล้อมรอบตัว stickman ที่เรากดลงไปนั่นเองดังรูป


Kivy(Graphic and canvas)

  เราจะเริ่มทำการวาดออกมาเป็นรูปต่างๆและวิธีการแสดงผลรูปที่เราวาดไปผ่านคำสั่งที่่ใช้บน canvasโดยเราจะทำการวาดรูปพื้นฐาน(เส้นตรง,เส้นโค้ง,วงรี)ผ่านชุดคำสั่ง vertex และนอกเหนือจากนี้เราจะทำการวาดลงสี,หมุนรุป ย่อขยายรูปเราก็สามารถทำได้ผ่านชุดคำสั่ง context widgets แต่ละตัวนั้นมี canvas เป็นของตัวเองอยู่แล้วแต่ว่าทั้งหมดนั้นจะมีการแบ่งปันพื้นที่ที่เป็นจุดร่วมกันโดยความสำคัญอีกอย่างนึงของ widgets คือ ตัว widgets นั้นมีจุดที่ไว้ใช้บอกตำแหน่งอยุ่แล้วแต่ว่าไม่ใช่ตัวที่เก็บตำแหน่งและ canvas ของ widgets ตัวนั้นจะไม่สามารถเข้าถึงค่าตำแหน่งของตัว widgets ได้จะมีโค้ดตัวอย่างมาให้เราดูคือ

โค้ดจากไฟล์ .py

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

class DrawingSpace(RelativeLayout):
    pass

class DrawingApp(App):
    def build(self):
        return DrawingSpace()

DrawingApp().run()

โค้ดจากไฟล์ .kv

<DrawingSpace>:
  canvas:
    Rectangle:
      pos: self.x+10,self.top-80
      size:self.width*0.15,self.height*0.3
    Ellipse:
      angle_start: 120
      angle_end: 400
      pos: 150, root.top-80
      size: 80, 80

และจากตัวอย่างโค้ดด้านบนนั้นจะทำให้เราได้ผลลัพธ์ที่แสดงออกมาคือ


โดยจะมีอีก 2 เรื่องที่เหลือคือการใส่สีลงไปบนรูปและการหมุนรูปโดยไม่จำเป็นต้องไปโฟกัสเท่าไหร่มาต่อกันที่การวาดตัว stickman ในคราวนี้จะให้มันทำการเพิ่มตัว stickman เข้าไปจากตัวอย่างท้ายบทที่ 1 โดยเริ่มจากการเพิ่มไฟล์เข้าไปตัวนึงคือ comicwidgets.kv โดยจะต้องใช้คำสั่ง builder เพิ่มเข้าไปอีก 1 บรรทัดในไฟล์ comiccreator.py โดยให้โค้ดมาดังนี้

โค้ดในไฟล์ comicwidgets.kv

<StickMan@RelativeLayout>:
  size_hint: None,None
  size:48, 48
  canvas:
    PushMatrix
    Line:
      circle: 24,38,5
    Line:
      points: 24,33,24,15
    Line:
      points: 14,5,24,15
    Line:
      points: 34,5,24,15
    Translate:
      y: 48-8
    Rotate:
      angle: 180
      axis: 1,0,0
    Line:
      points: 14,5,24,15
    Line:
      points: 34,5,24,15
    PopMatrix

โดยจะเห็นว่ามีคำสั่ง PushMatrix คือคำสั่งที่ใช้เก็บค่าก่อนที่จะเปลี่ยนแปลงทั้งหมดไว้และใช้คำสั่ง PopMatrix คือการคืนค่าที่เก็บไว้คืนมายังไม่หมดเราต้องทำการแก้ไฟล์ toolbox.kv และ drawingspace.kv เพิ่มอีกด้วย

โค้ดในไฟล์ toolbox.kv

<ToolButton@ToggleButton>:
  size_hint: None,None
  size: 48,48
  group: 'tool'
  canvas:
    PushMatrix:
    Translate:
      xy: self.x,self.y
  canvas.after:
    PopMatrix:
<ToolBox@GridLayout>:
  cols: 2
  padding: 2
  ToolButton:
    canvas:
      Line:
        circle: 24,24,14
  ToolButton:
    canvas:
      Line:
        points: 10,10,38,38
  ToolButton:
    StickMan:
      pos_hint: {'center_x' : .5, 'center_y' : .5}

โค้ดในไฟล์ drawingspace.kv

<DrawingSpace@RelativeLayout>:
  Label:
    markup: True
  StickMan:
    pos_hint: {'center_x': .5, 'center_y':.5}
    canvas.before:
      Translate:
        xy:-self.width/2 , -self.height/2
      Scale:
        xyz: 2, 2, 0
  StickMan:

และหลังจากเราทำการแก้โค้ดทั้งหมดเราก็จะได้ผลลัพท์แสดงหน้าจอใหม่คือ


วันจันทร์ที่ 21 กันยายน พ.ศ. 2558

Kivy(Layout)

Layouts
  Layout คือรูปแบบในการจัดวาง widgets โดยแต่ละ layout ที่ทาง Kivy ได้จัดมาให้เรานั้นจะมีอยู่หลายแบบด้วยกันโดยแต่ละแบบนั้นจะมีลักษณะการจัดวางที่ต่างกันออกไปโดยในที่นี้มีอยู่ 7 แบบเริ่มที่

1.FloatLayout

  Floatlayout โดย layout แบบนี้นั้นจะใช้แบบหน้าต่าง size ของจอแสดงผลการทำงานของโค้ดเรานั้นมีสเกลเริ่มต้นที่ 0 และสุดที่ 1 โดยจะให้เราสามารถเลือกตำแหน่งที่ต้องการจัดว่าตัว widgets ได้โดยใช้ตัวเลขทศนิยม(0.0-1)เพื่อเลือกตำแหน่งที่ใช้ในการจัดวาง widgets ของเรายกตัวอย่างโค้ดเช่น

โค้ดในไฟล์ .py

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout

class FloatLayoutApp(App):
    def build(self):
        return FloatLayout()

FloatLayoutApp().run()

โค้ดในไฟล์ .kv

<Button>:
  color: .8,.9,0,1
  font_size: 32
  size_hint: .4, .3

<FloatLayout>:
  Button:
    text: 'Hello'
    pos_hint: {'x': 0, 'top':1}
  Button:
    text: 'world!'
    pos_hint: {'right': 1, 'y':0}

โดยเราจะเห็นว่ามีคำสั่งเพิ่มเติมขึ้นมาคือ pos_hint กับ size_hint ซึ้งเป็นคำสั่งที่เราใว้ใช้กำหนดตำแหน่งของ widgets โดยมีการกำหนดเป็นสเกลแบบทศนิยมนั้นเอง
จากโค้ดด้านบนผลลัพท์ที่ได้


จะเห็นได้ว่าจากไฟล์ .kv นั้นเราได้ทำการกำหนดปุ่มแรกที่มีคำว่าHello นั้นไว้ที่จุด x=0 และ top = 1 ซึ่งก็คือค่าในแนวแกน x คือ0 คือชิดขอบด้านซ้ายและ top คือแถบบนของตัวปุ่มในแนวแกน y จะชิดกันกับขอบบนสุดของหน้าต่างซึ่งอีกปุ่มนึงก็ทำในหลักการเดียวกันเลยไปอยู่ชนกับขอบล่างสุดขวาสุดของหน้าต่างซึ่งถ้าเราลองเปลี่ยนค่าในแนวแกน y ที่ไฟล์ .kv เป็น 0.5 ตัวbutton hello ก็จะถูกเลื่อนลงมาและตัว button world! ก็จะถูกเลื่อนขึ้นไปแทน


2.Relative Layout
  ในส่วนของ layout นี้ก็ยังใช้หลักการเดียวกันกับ floatlayout เพียงแต่ว่าค่า 0-1 นั้นจะสัมพันธ์กับ size ของตัว layout เองไม่ได้สัมพันธ์กับค่าจอแสดงผล(window size)เหมือนอย่าง floatlayout

3.Grid Layout
 จะใช้คอลั่มกับแถวเข้ามาช่วยโดยจะมีคำสั่ง col: กับ row: เพิ่มขึ้นมา

4.Box Layout
  ค่าที่ใช้กำหนดในlayout นี้นั้นจะเป็นค่าที่ขึ้นอยู่กับในแนวตั้งและแนวยาว

5.Stack Layout
  layout นี้มีความคล้ายคลึงกับ Box layout แต่ว่าถ้าหมดแถวนึงหรือคอลั่มนึงแล้วจะทำการขึ้นแถวหรือคอลั่มนั้นใหม่โดยที่ layout นี้มีความยืดหยุ่นในการใช้งานมากกว่า box layout โดยจะมีตัวกำหนดค่ามาช่วยให้ใช้งานได้ง่ายขึ้นคือlr(left to right),rl(right to left),tb(top to bottom),bt(bottom to top)

6.Anchor Layout
  มีความสามารถในการจัดการ widgets ให้อยู่ในกรอบหรืออยู่ตรงกลางได้โดย anchor_x_property แสดงถึงตำแหน่งในแกน x และ anchor_y_property แสดงถึงพิกัดในแกน y

7.Scatter Layout
  การใช้งานคล้ายคลึงกับ Relative layout แต่ว่ามีลุกเล่นเยอะกว่าตรงการใช้ multitouch ได้หรือแม้แต่กลับด้าน แปลภาษา ก็ยังสามารถทำได้ซึ่งในหนังสือไม่ได้เจาะรายละเอียดมาให้

Embeding layouts
  คือการฝังตัวของ layouts โดยจะให้โค้ดตัวอย่างที่ใช้ทดสอบมาคือ

โค้ดในไฟล์ .py

from kivy.app import App
from kivy.uix.gridlayout import GridLayout

class MyGridLayout(GridLayout):
    pass

class LayoutsApp(App):
     def build(self):
        return MyGridLayout()

LayoutsApp().run()

จะเห็นได้ว่าโค้ดด้านบนนั้นไม่ได้มีอะไรแตกต่างจากโค้ดก่อนๆเท่าไหร่เพียงแต่ว่าเราได้ทำการนำ Gridlayouts เข้ามาใช้งานเเพื่อช่วยแสดงผลตัวอย่าง layouts ทั้งหมดนั้นเองโดยจะแบ่งได้เป็นส่วนๆ 5ส่วนย่อยโดยจะประกอบด้วย

โค้ดในไฟล์ .kv
  ส่วนที่:1

<MyGridLayout>:
  rows: 2
  FloatLayout:
    Button:
      text: 'F1'
      size_hint: .3, .3
      pos:0, 0
  RelativeLayout:
    Button:
      text: 'R1'
      size_hint: .3, .3
      pos: 0,0

  ส่วนที่:2

  GridLayout:
    cols: 2
    spacing: 10
    Button:
      text: 'G1'
      size_hint_x: None
      width: 50
    Button:
      text: 'G2'
    Button:
      text: 'G3'
      size_hint_x: None
      width: 50

  ส่วนที่:3

  AnchorLayout:
    anchor_x: 'right'
    anchor_y: 'top'
    Button:
      text: 'A1'
      size_hint:[.5, .5]
    Button:
      text: 'A2'
      size_hint: [.2, .2]

  ส่วนที่:4

  BoxLayout:
    orientation: 'horizontal'
    Button:
      text: 'B1'
    Button:
      text: 'B2'
      size_hint: [2,.3]
      pos_hint: {'y',.4}
    Button:
      text 'B3'

  ส่วนที่:5

  StackLayout:
    orientation: 'rl-tb'
    padding: 10
    Button:
      text: 'S1'
      size_hint: [.6,.2]
    Button:
      text: 'S2'
      size_hint: [.4,.4]
    Button:
      text: 'S3'
      size_hint: [.3,.2]
    Button:
      text: 'S4'
      size_hint: [.4,.3]

จากโค้ดจากด้านบนทั้งหมดจะได้ผลลัพธ์แสดงเป็นตัวอย่างของแต่ละ layouts ให้เราเห็นคือ


(ภาพจากหนังสือKivy-Interactive-Applications-in-Python)

จากผลลัพท์ที่เราได้นั้น(ยืมภาพมาจากหนังสือ)จะเห็นได้ว่าแต่ละรูปนั้นแสดงถึง layout แต่ละแบบว่ามีคุณสมบัติ ลักษณะอย่างไรบ้างซึ่งสามารถนำไปปรับใช้ได้ในต่อๆไป

Comic-Creator
  เราได้รู้เกี่ยวกับคุณสมบัติที่จะใช้ในการสร้าง interface ไปทั้งหมดแล้วในส่วนนี้จะเกี่ยวกับการสร้างพื้นฐานคือการวาด stickman แล้วมี interface ไว้รับค่า sketch คือในรูปด้านล่างนี้


(ภาพจากหนังสือKivy-Interactive-Applications-in-Python)

โดนจากภาพ sketch เบื้องต้นด้านบนเราควรจะเลือก layouts ที่ใช้งานให้เหมาะสมเพื่อสะดวกในการจัดการโดยทางหนังสือที่อ่านแนะนำให้เลือกดังนี้
  Anchor layouts ใช้กับกล่องเครื่องมือด้านบนซ้ายมือ
  Grid layouts สำหรับคอลั่มเลือกฟังก์ชั่นด้านล่าง
  Anchor layouts ใช้สำหรับช่องว่างข้างบนขวามือ
  Relative layouts ใช้สำหรับจัดการตำแหน่งในช่องขวาบนเพื่อจัดตำแหน่ง stickman
  Anchor layouts ใช้สำหรับการสร้างกล่องแสดงสถานะด้านล่างสุด
  Box layouts ใช้สำหรับสร้างกล่องข้อความฟังก์ชั่นด้านล่างเพื่อให้เราสามารถกำหนดอัตราส่วน

โดยจากการร่างก่อนว่าจะทำอะไรด้านบนนั้นทางหนังสือก็มีตัวอย่างโค้ดมาให้ลองว่าจะได้ผลลัพท์หรือไม่

โค้ดจากไฟล์ .py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout

Builder.load_file('toolbox.kv')
Builder.load_file('drawingspace.kv')
Builder.load_file('generaloptions.kv')
Builder.load_file('statusbar.kv')

class ComicCreator(AnchorLayout):
    pass

class ComicCreatorApp(App):
    def build(self):
        return ComicCreator()

ComicCreatorApp().run()

โค้ดจากไฟล์.kv

<ComicCreator>:
  AnchorLayout:
    anchor_x: 'left'
    anchor_y: 'top'
    ToolBox:
    id: _tool_box
    size_hint: None,None
    width: 100
  AnchorLayout:
    anchor_x: 'right'
    anchor_y: 'top'
    DrawingSpace:
    size_hint: None,None
    width: root.width - _tool_box.width
    height: root.height - _general_options.height-_status_bar.height
  AnchorLayout:
    anchor_x: 'center'
    anchor_y: 'bottom'
    BoxLayout:
      orientation: 'vertical'
      GeneralOptions:
    id: _general_options
    size_hint: 1,None
    height: 48
      StatusBar:
    id: _status_bar
    size_hint: 1,None
    height: 24

โค้ดจากไฟล์ toolbox.kv

<ToolButton@ToggleButton>:
  size_hint: None,None
  size: 48,48
  group: 'tool'

<ToolBox@GridLayout>:
  cols:2
  padding:2
  ToolButton:
    text: 'O'
    toolButton:
    text: '/'
  ToolButton:
    text: '?'

โค้ดจากไฟล์ drawingspace.kv

<DrawingSpace@RelativeLayout>:
  Label:
    markup: True
  text: '[size=32px][color=#3e6643]The[/color] [sub]Comic[/sub]
[i][b]Creator[/b][/i][/size]'

โค้ดจากไฟล์ generaloptions.kv

<GenaralOptions@BoxLayout>:
  oriention: 'horizontal'
  padding: 2
  Button:
    text: 'Clear'
  Button:
    text: 'Remove'
  Button:
    text: 'Group'
  Button:
    text: 'Color'
  Button:
    text: 'Gestures'

โค้ดจากไฟล์ statusbar.kv

<StatusBar@BoxLayout>:
  orientation: 'horizontal'
  Label:
    text: 'Total Figures: ?'
  Label:
    text: "Kivy started"

และจากโค้ดข้างบนทั้งหมดจะได้ผลลัพท์ออกมาดังรูปภาพด้านล่างนี้


วันพุธที่ 16 กันยายน พ.ศ. 2558

Kivy(Button&Widgets)

  ในส่วนของ Kivy จะมองเป็นเหมือน library เพิ่มขึ้นมาใน python ไว้ให้เรา import เข้ามาแล้วให้เราเรียกใช้งานมันได้โดย Kivy นั้นจะทำให้เราสามารถวาดรูปหรือสิ่งต่างๆออกมาได้โดยในปกติแล้วpython ไม่สามารถวาดรูปได้ แต่ถ้ามีการ import เข้ามาก็จะสามารถใช้งานได้โดยเราต้องทำการติดตั้ง Kivy ลงไปใน ระบบปฏิบัจิการของเราก่อนโดยถ้าใช้งานใน ubuntu เราก็สามารถติดตั้งได้โดยใช้คำสั่งตามนี้

  sudo add-apt-repository ppa:kivy-team/kivy

  sudo apt-get update

  sudo apt-get install python3-kivy

เมื่อทำการเรียกใช้คำสั่งทั้งหมดเสร็จแล้วเราก็สามารถเรียกใช้งานตัว Kivy ได้โดยจะมีตัวอย่างให้ดูโดยเราต้องทำการเรียกใช้ คำสั่ง นี้

  sudo apt-get install kivy-examples

โดยเมื่อทำการติดตั้งเรียบร้อยแล้วจะมีตัวอย่างให้เราสามารถมาดูได้เยอะพอสมควร

 
ละจากการศึกษา Kivy จากหนังสือ Kivy-Interactive-Applications-in-Python นั้น
เรื่องแรกจะเป็นเรื่องเกี่ยวกับ การใช้งาน Kivy เบื้องต้นโดยจะมีตัวอย่างโค้ดมาให้โดยตัวอย่างโค้ดแรกนั้นก็คือ

from kivy.app import App#ดึง kivy มาใช้โดยให้เหมือนเป็นคลาสแม่
from kivy.uix.button import Label#ดึงส่วนนึงของ kivy มาใช้เป็นตัวแสดงผลในชื่อ Label


class HelloApps(App):#สร้างคลาสโดยสร้างเป็นคลาสลูกของ App
    def build(self):#เรียกใช้เมทอดเพื่อสร้างหน้าต่างแสดงผล
        return Label(text = 'Hello world')#คืนค่าตัวแสดงผลโดยให้แสดงคำว่า'Hello World!'


HelloApps().run()

  กล่าวต่อไปคือ kivy นั้นไม่ได้เป็นแค่ library ของ python ทั้งหมดเรายังสามารถเพิ่มเติมคำสั่งเข้าไปเองได้โดยใช้การสร้างไฟล์ .kv ขึ้นมาแล้วทำการตั้งชื่อเหมือนกันกับไฟล์ .py และอยู่ในพื้นที่เดียวกันกับไฟล์ .py เพื่อให้คำสั่งมาเรียกใช้เพิ่มเติมจากไฟล์.kvได้อีกด้วย(เราสามารถสร้างไฟล์.kyโดยใช้notepad ใน window หรือ texteditor ใน ubuntu)
จากนั้นก็จะมีโค้ดตัวอย่างมาให้คือ

from kivy.app import App
from kivy.uix.button import Label

class HelloApps2(App):
    def build(self):
        return Label()#ต่างกับอันแรกแค่ไม่มีการส่งค่าเข้าไป


HelloApps2().run() 

และให้เราสร้างไฟล์ .kv ขึ้นมาโดยให้ตัวอย่างโค้ดมาดังนี้

<Label>:
   text = 'Hello World!'

ให้เรานำทั้ง 2 ไฟล์ไปไว้ใน directory เดียวกันและทำการเรียกใช้โดยผลลัพท์ที่ได้จะได้เหมือนกับในตัวอย่างที่ 1 เพียงแต่เราสามารถแก้ไขคำที่เราจะแสดงได้ในไฟล์ .kv ไม่จำเป็นต้องไปแก้ในโค้ด
(หากเราต้องการลดหน้าต่างการแสดงผลให้เล็กลงสามารถไปเรยกใช้ใน terminal(ubuntu)หรือ commandline(window)เพื่อทำการเลือกไซส์แสดงผลเองได้โดยให้เราใช้คำสั่ง python <name>.py --size=(width)x(height) จะแสดงผลออกมาให้เราเลยแต่ไซส์จะเท่าที่เรากำหนดไว้)

ตัวอย่างต่อมาจะเป็นการสร้าง widgets แบบพื้นฐานโดยในตัวอย่างที่แล้ว Label ก็เป็น widgets ตัวนึงที่ Kivy นั้นมีให้เราใช้และยังมีอีกหลายตัวยกตัวอย่างเช่น button,label,checkboxes โดยตัว widgets นั้นจะเป็นการสร้างเพื่อทำเป็น interface ติดต่อกับผู้ใช้งาน
โดยตัวอย่างโค้ดที่ได้เป็นดังนี้

from kivy.app import App
from kivy.uix.widget import Widget#ดึงในส่วนwidgetsมาใช้

class MyWidget(Widget):
    pass

class widgets(App):
    def build(self):
        return MyWidget()

widgets().run() 


โดยเราต้องทำการสร้างไฟล์ .kv มาอีกไฟล์เพื่อทำการเขียน widgetsของเราเองโดยในหนังสือให้ตัวอย่างโค้ดที่ต้องนำมาเขียนในไฟล์ .kv คือ

<MyWidget>:#ในคลาส widgets จะให้เรามาเขียนเองตรงนี้

  Button:#เป็นการสร้างส่วนแสดงผลแบบเป็นปุ่ม
    text:'Hello'#แสดงผลคำว่า Hello
    pos: 0, 100#แสดงในตำแหน่ง x = 0, y = 100
    size: 100,50#กำหนดขนาด
    color: .8,.9,0,1#กำหนดสี
    font_size: 32#กำหนดขนาดตัวอักษร


  Button:
    text:'World!'
    pos: 100, 50
    size: 100, 50
    color: .8,.9,0,1
    font_size: 32


และให้เราตั้งชื่อไฟล์ทั้ง 2 ไฟล์เป็นชื่อเดียวกันแต่นามสกุลต่างกันนมาไว้ในที่เดียวกันเมื่อเรียกใช้จะได้ผลลัพท์ที่ได้คือ


แต่จะเห็นได้ว่าตำแหน่งนั้นเราได้ทำการระบุค่าไว้แล้วซึ่งเมื่อเรานำไปกด size ที่เล็กกว่าค่าที่ระบุไว้ก็จะทำให้ปุ่มที่เราสร้างขึ้นมานั้นมองไม่เห็นตัวอย่างโค้ดต่อไปเลยเป็นการนำตัวแปรของระบบมาใช้งานโดยโค้ดคือ

<Mybutton@Button>:
  color: .8,.9,0,1
  font_size: 32
  size: 100, 50

<MyWidget>:


  Mybutton:
    text: 'Hello'
    pos: root.x, root.top-self.height


  Mybutton:
    text: 'World!'
    pos: root.right - self.width , root.y
 


จากตัวอย่างโค้ดอันนี้จะเห็นได้ว่าค่าตำแหน่งถูกแทนด้วยตัวแปรของระบบซึ่งจะลองดูผลลัพท์ที่ได้คือ 


 Size = 200x150

 

Size = 400x300



จะเห็นไดว่าถึงขนาด size จะใหญ่ขึ้นหรือเล็กลงตัว widgets ของเรานั้นก็จะยังอยู่ที่เดิมต่างจากตัวอย่างโค้ดอันแรกที่ตัวwidgetsจะไม่เปลี่ยนตามขนาดไซส์