id
.kv 내에서만 접근 가능한 아이디다.
보통 맨 앞에 _를 붙이지만, 구분하기 위한 권고사항이지 필수는 아니다
attribute
어떤 widget에 attribute를 생성하고, id를 여기 넣어주면 그 attribute로 접근할 수 있다.
<ComicCreator>:
AnchorLayout: ...
ToolBox:
id: _tool_box
drawing_space: _drawing_space
AnchorLayout: ...
DrawingSpace:
id: _drawing_space
commiccreator.kv의 ToolBox에서 drawing_space attribute는 _drawing_space(id)를 가지고 있으며, python에서 drawing_space로 여기에 접근 가능하다.
root도 동일한 방식이다.
etc.
root: base widget in the rule hierarchy
self: current widget
app: the instance of the application
Touch event
touch event는 mouse, finger touch, magic pen touch으로 나뉘며, 아래 event는 mouse, finger touch에서 사용 가능하다.
- on_touch_down: new touch start
- on_touch_move: the touch is moved
- on_touch_up: the touch ends
각 touch event는 parameter(touch)로 여러 정보를 갖는 MotionEvent를 받는다.
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)
event가 진행되면 True
를 return하고, event가 widget 밖으로 나가면, children에 전달해 return을 받는다.
유사하게 super.on_touch_~ 으로 chidren의 event를 신경쓸 수 있다.
collide_point
모든 widget이 app(coordinate space)에서 발생하는 touch event(MotionEvent)를 받지만, 그 event가 특정 widget에서 발생하는지 확인하는 보편적인 방법이다.
dynamic create/deleate canvas
with self.canvas:
self.selected = Line(rectangle=(0, 0, self.width, self.height),
dash_offset=2)
with self.canvas
를 통해 canvas에 instructions를 넣을 수 있다.
Line instance를 self.selected
에 넣어서 언제든 삭제할 수 있도록 구현할 수 있다.
if self.selected:
self.canvas.remove(self.selected)
self.selected = None
self.canvas.remove(self.selected)
를 통해 canvas에 self.selected를 지울 수 있다.
localizing coordinates
to_parent()
같이, 현재 widget에서 구현하지만, 움직일 공간이 parent, 혹은 parent’s parent와 같은 경우 coordinates의 범위를 지정해주는 것.
RelativeLayout은 coordinate의 위치 값들이 다 다르기 때문에 이런 방법이 필요하다.
-
RelativeLayout이 아닌 layout들은 그 상위에 대해 절대적인 coordinate 값을 가지고 있음
- to_parent(): transform relative coordinates inside RelativeLayout to the parent of RelativeLayout. 부모의 coordinate에 접근할 수 있다.
- to_local(): transform the coordinates of parent of RelativeLayout to RelativeLayout
- to_window(): transform the coordinates of the current widget to absolute coordinate with respect to the window
- to_widget(): transform the absolute coordinates to coordinates within the parent of the current widget
.py와 .kv 연결
layout.add_widget(w)
으로 layout에 widget을 더해준다.
#:import toolbox toolbox
으로 toolbox를 .kv에 import 한다. (.kv에서도 python code를 import할 수 있다.)
comiccreator.py comiccreator.kv (얘가 toolbox를 사용) - toolbox.py - toolbox.kv
위와 같이, commiccreator가 main이 되고 toolbox를 사용하는 상황에서
- comiccreator.py에서 comiccreator.kv를 사용하고 (kv에서 자동으로)
- commiccreator는 toolbox.kv를 내부적으로 사용하고 (.py에서
Builder.load_file
로 load) - toolbox.kv는 toolbox.py의 구현을 사용한다 (.kv에서
#:import toolbox toolbox
로 import)
즉, toolbox.py가 main이었다면 import를 안해도 .kv를 가져갔겠지만, toolbox가 main이 아니라 사용되는 상황에서, .py를 import 해줘야 했음.
bind/unbind
binding에는 2가지 방법이 존재한다.
1. at .py, it works for every instance about this class
python에서는 bind하면 전체 적용되는 것을 피하기 위해 touch_down의 경우 overriding하여 사용하고, 나머지에 대해 bind 하는 방식을 사용한다.
(we didn’t want the on_touch_move
, on_touch_up
events active all the time.)
move와 up은 touch_down이 발생한 이후에 발생할 수 있으므로, 이 이벤트들을 항상 active 상태에 두는 것이 아니라, touch_down시에 bind를 통해 관리하도록 하는 것이다.
def on_touch_down(self, touch):
...
self.draw(ds, x, y)
def draw(self, ds, x, y):
...
ds.bind(on_touch_move=self.update_figure)
ds.bind(on_touch_up=self.end_figure)
def update_figure(self, ds, touch):
def end_figure(self, ds, touch):
2. at .kv, it works only for this instance
특정 instance에 대해 bind하기 때문에 collide_point를 사용할 필요가 없다.
- Button:
on_press:
와on_release:
<GeneralOptions>:
Button:
text: 'Clear'
on_press: root.clear(*args) # clear, remove는 .py의 GeneralOptions에 구현된 함수
Button:
text: 'Remove'
on_release: root.remove(*args)
- ToggleButton:
on_state
- .py에서 ‘down’, ‘normal’로 구분
etc
clear_widgets()
: 모든 widget을 지움remove_widget(x.children[0])
: 가장 최근에 추가된 widget을 지움
Kivy property
property가 정의되면 Kivy는 내부적으로 property와 연관된 event를 생성하고, 이 event는 ‘on_property_name’ method와 연결된다.
translation = ListProperty(None)
def on_translation(self, instance, value):
따라서, property에 값을 넣어주면 on_property 가 자동으로 실행 된다.
- 이는 kivy에서 굉장히 중요한 개념으로, 내부적으로 많이 사용됨.
- 다른 클래스에서 특정 property를 바꿈으로써 on_property를 trigger할 수 있음.
center_x
도 property를 내부적으로 사용하는 것이다.
.kv의 vertex instruction의 attribute도 내부적으로 property로 사용 된다.
python property와 혼동해서는 안된다.
Kivy Property는 항상 attribute 지만, attribute가 모두 Kivy Property는 아니다.
- attribute: used to describe variables(references, objects, instances) that belongs to class
class StatusBar(BoxLayout):
counter = NumericProperty(0)
previous_counter = 0
kivy property는 static attribute로 선언되나, internally transformed to attribute instansces.
counter
는 static하게 선언되나 attribute instances가 되고,previous_counter
는 static attribute로 되어 all StatusBar가 share..- class name(
StatusBar.previous_counter
)이나__class__
(__class_.previous_counter
)로 바로 접근 가능
- class name(
__init__
안에서 선언되는 것들은 instance 임. 즉 not shared..
Kivy property
BoundedNumericProperty: set the maximum and minimum values
AliasProperty: extend the properties, create our own properties
NumericProperty
StringProperty
ListProperty
DictProperty
ObjectProperty
StringProperty