LoginSignup
3
2

More than 5 years have passed since last update.

(翻訳) Kivyにおける回転と移動と拡大縮小とRelativeLayout

Last updated at Posted at 2017-04-21

はじめに

 Kivyに関する調べ物をしていて見つけた記事が凄く面白かったので、許可をもらって翻訳しました。

原文の著者

 Roberto Ulloaさんという方です。that doesn't make any sense…というBlogを公開していて、今回の翻訳はそこに書かれていた記事の一つです。又Kivyに関する以下の本も出版しているようで、

Kivyの(というかProgrammingの)かなりの熟練者のようです。

原文:
 Rotate, Translate, Scale and RelativeLayout in Kivy
 Rotate, Translate, Scale and RelativeLayout in Kivy – undercovered!

 私はKivyにおいて変換(回転、移動、拡大縮小)をしようとして躓いています。ドキュメントがいうには「各Widgetは元からそれぞれのCanvasを持っている」だそうですが、実際には全てのWidgetが同じCanvasを共有しているようにしか思えないのです。以下のコードを見て下さい。

main.py
from kivy.app import App
from kivy.uix.widget import Widget


class Example(Widget):
    pass


class ExampleApp(App):

    def build(self):
        return Example()


ExampleApp().run()
example.kv
<Example>:
    Button:
        pos: [0,0]
        size_hint: [None, None]
        size: [200,200]
        canvas.after:
            Line:                      # A
                circle: [50, 100, 50]  # A
            Translate:                 # B
                x: 100                 # B
            Line:                      # C
                circle: [50, 100, 50]  # C
    Button:
        pos: [200,0]
        size_hint: [None, None]
        size: [200,200]
        background_color: [0,0,1,1]

 大きさ(200, 200)のButtonが二つありますね。私はそれらを横に並べたかったので一つは座標(0, 0)に、もう一つは座標(200, 0)に配置しました。それから一つ目のButtonには次の様に二つの円を横に並ぶように描きました。

  1. 座標(50, 100)を中心に半径50pxの円を描画(A行)
  2. 座標系をxの正方向に100px(円の直径分)ずらす(B行)
  3. 座標(50, 100)を中心に半径50pxの円を描画(C行)

そして以下のコマンド

python main.py --size=500x200

を実行したところ結果は以下のようになりました。

screenshot1

どうしてButtonの間に黒い隙間があるの!?期待していたのは以下の結果なのに。

screenshot2

 どうやらB行のTranslateがその後の描画命令全てに影響しているようです。それも自身のWidgetだけでなくWindow全体に。だから私はCanvasが共有されているようにしか思えないのです。

解決法

 上記の問題を直すには以下の方法があります。

方法1 行った座標系に対する操作を個別に戻す

example.kv
<Example>:
    Button:
        pos: [0,0]
        size_hint: [None, None]
        size: [200,200]
        canvas.after:
            Line:
                circle: [50, 100, 50]
            Translate:
                x: 100
            Line:
                circle: [50, 100, 50]
            Translate:   # 追加した行
                x: -100  # 追加した行
    Button:
        pos: [200,0]
        size_hint: [None, None]
        size: [200,200]
        background_color: [0,0,1,1]

方法2 RelativeLayoutを使う

ButtonをRelativeLayoutの中に入れるだけで解決します。

example.kv
<Example>:
    RelativeLayout:
        pos: [0,0]
        Button:
            pos: [0,0]
            size_hint: [None, None]
            size: [200,200]
            canvas.after:
                Line:
                    circle: [50, 100, 50]
                Translate:
                    x: 100
                Line:
                    circle: [50, 100, 50]
    Button:
        pos: [200,0]
        size_hint: [None, None]
        size: [200,200]
        background_color: [0,0,1,1]

方法3 PushMatrixとPopMatrixを使う

example.kv
<Example>:
    Button:
        pos: [0,0]
        size_hint: [None, None]
        size: [200,200]
        canvas.after:
            PushMatrix:
            Line:
                circle: [50, 100, 50]
            Translate:
                x: 100
            Line:
                circle: [50, 100, 50]
            PopMatrix:
    Button:
        pos: [200,0]
        size_hint: [None, None]
        size: [200,200]
        background_color: [0,0,1,1]

PushMatrixとPopMatrixによってMatrixの状態を保存復元しているわけです。そしてこれはRelativeLayoutが内部で行っていることでもあります。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2