Kivyのペイントアプリを拡張した話

#はじめに
Python Advent Calendar 2016の初日に飛び込みました。初日だからみんな見てくれるはず・・・。
http://qiita.com/advent-calendar/2016/python

なんでもアリらしいので、Kivyのお話。(6ヶ月前ほどの少し古いネタ)

# ペイントアプリを拡張
Kivyのチュートリアルに簡単なペイントアプリのサンプルがあります。
https://kivy.org/docs/tutorials/firstwidget.html
このペイントアプリ、描画するたびに描画する色が変わります。

``` python
class MyPaintWidget(Widget):

    def on_touch_down(self, touch):
        color = (random(), 1, 1)
        with self.canvas:
            Color(*color, mode='hsv')
            d = 30.
            Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
            touch.ud['line'] = Line(points=(touch.x, touch.y))
```

ソースコードでも color = (random(), 1, 1) で毎回、ランダムに色を入れているこがわかります。実行すると以下、画像の通り。
<img src="https://qiita-image-store.s3.amazonaws.com/0/98851/2fd1c23f-3ea9-8139-ae9c-3c0ad8601c6e.png" width="300px">

でも、どうせなら自分で色変えたいと思ったので少し拡張してみました。
Kivyには実験的にですがColorPickerのウィジェットがあるのでそれを使います。
https://kivy.org/docs/api-kivy.uix.colorpicker.html

ちなみにこんなやつ
<img src="https://qiita-image-store.s3.amazonaws.com/0/98851/29ca09d6-6e16-b911-2580-2775424e15de.png" width="300px">


以下のようにプログラムを書き換えて、Kvをガリガリと書きました。

``` python:main.py
#from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.colorpicker import ColorPicker
from kivy.graphics import Color, Ellipse, Line

class ClearButton(Button):
    pass

class ColorChangeButton(Button):
    pass
        
class MyPopup(Popup):
    pass

class MyPaintWidget(Widget):
    color = [1, 1, 1, 1]
    def on_touch_down(self, touch):
        with self.canvas:
            Color(rgba=(self.color))
            d = 5
            Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
            touch.ud['line'] = Line(pos=(touch.x, touch.y))

    def on_touch_move(self, touch):
        touch.ud['line'].points += [touch.x, touch.y]
    
    def clear_canvas(self,*largs):
        self.canvas.clear()
        
    def open_popup(self):
        popup = MyPopup()
        popup.open()

class MyPaintApp(App):
    def build(self):
        parent = Widget()
        self.painter = MyPaintWidget()
        clearbtn = ClearButton()
        colorbtn = ColorChangeButton()
        parent.add_widget(self.painter)
        parent.add_widget(colorbtn)
        parent.add_widget(clearbtn)
        return parent
    
if __name__ == '__main__':
    MyPaintApp().run()

```

``` kv:mypaint.kv
<ClearButton>:
    Button:
        text: 'Clear'
        right: root.right
        top: root.top
        width: 100
        height: 100
        on_release: app.painter.canvas.clear()

<ColorChangeButton>:
    Button:
        text: 'Color'    
        right: root.right
        top: root.top
        width: 100
        height: 100
        on_release: app.painter.open_popup()
        
<MyPopup>:
    title: 'Color Select'
    size_hint: None, None
    size: 400, 400
    BoxLayout:
        orientation: 'vertical'
        ColorPicker:
            id: picker
            color: app.painter.color
            on_color: app.painter.color = self.color
            
        Button:
            size_hint_y: None
            height: 60
            text: 'Change'
            on_press: root.dismiss()
        
```


ColorPickerはKvで使用しました。使い方はこんな感じ。

```
<MyPopup>:
    title: 'Color Select'
    size_hint: None, None
    size: 400, 400
    BoxLayout:
        orientation: 'vertical'
        ColorPicker:
            id: picker
            color: app.painter.color
            on_color: app.painter.color = self.color
```

実行結果こんな感じ
<img src="https://qiita-image-store.s3.amazonaws.com/0/98851/cb528fae-946b-7613-f4d9-12817e0cad64.png" width="300px">

<img src="https://qiita-image-store.s3.amazonaws.com/0/98851/066feae5-eaf0-f56c-674e-eb826d18a263.png" width="300px">

<img src="https://qiita-image-store.s3.amazonaws.com/0/98851/dc85479f-b583-25b7-8648-193b3fe5e51c.png" width="300px">

無事、色が変わりました。
ColorPickerの情報が少なく、四苦八苦したのは良い思い出。

ソースコードはgithub上に置いてあります。
https://github.com/pyKy/Kivy-studies/tree/master/5th

以上、Kivyのお話でした。
もうちょっといろんなことがやりたい・・・。