LoginSignup
13
10

More than 5 years have passed since last update.

Kivyのcanvas命令でDocumentationに載ってない事、ややこしい事

Last updated at Posted at 2018-04-24

はじめに

Kivyのgraphics周りのDocumentationは抜けているところが多いので、ソースコードを読まないとわからないことが多いです。その上ソースコードはcython用なので、私のEditor(SublimeText)の持つソースコード参照機能や__doc__参照機能が使えず、調べるのに時間を要する事が多いです。なので自分なりによく使う機能や忘れやすい事をまとめました。

canvas命令全体図

all.png

InstructionGroup

doc, src
さっそくですがDocに載っていない物があります。ただもしかすると内部用の物で意図的に載せてないのかもしれません。

  • length() ...持っている描画命令の数を返すMethod
  • indexof(inst) ...instが内部の描画命令のlist上の何番目に位置するかを返すMethod

またmethodではないので明らかに内部用ですが、便利そうなので次の属性も挙げておきます。

  • children ...持っている描画命令のlist
from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
FloatLayout:
    canvas:
        Rectangle:
            size: self.size
            pos: self.pos
''')

canvas = root.canvas

print('命令の総数は', canvas.length())
for inst in canvas.children:
    print(inst)
print('{}の序数は{}'.format(inst, canvas.indexof(inst)))

runTouchApp(root)
標準出力
命令の総数は 2
<kivy.graphics.context_instructions.BindTexture object at 0x7f14b7a8ef78>
<kivy.graphics.vertex_instructions.Rectangle object at 0x7f14b7ee1688>
<kivy.graphics.vertex_instructions.Rectangle object at 0x7f14b7ee1688>の序数は1

Callback

doc,src

canvas命令ですがFactoryに登録されていないのでKv言語からは利用できません。

追記2018/07/29

最新版(master branch)のKivyではKv言語からも利用可能になりました。

Widget:
    canvas:
        Callback:
            callback: lambda __: setattr(self, 'callback_test', 'TEST')

ScissorPush, ScissorPop

doc,src

描画範囲を指定した長方形内に制限します。

from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
FloatLayout:
    canvas:
        ScissorPush:
            size: int(self.width *0.7), int(self. height *0.7)
            pos: 0, 0
        Ellipse:
            size: self.size
            pos: self.pos
        ScissorPop:
''')

runTouchApp(root)

Screenshot at 2018-04-24 18-31-20.png

ScissorPushに渡す長方形の座標は

  1. int型で指定しないといけない
  2. 常にWindow座標系

なのが注意点。またここでもDocの書き忘れがあり、それはx,yを纏めて設定できるposwidth,heightを纏めて設定できるsizeです。

StencilXXX系

doc,src
ScissorXXXとは違って自由度の高い描画領域の制限が行える。

from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
RelativeLayout:
    canvas:

        StencilPush:

        # 段階1: ここでの描画は実際には行われず、段階2での描画の範囲を決めるのにだけ使われる
        Rectangle:
            size: self.width * 0.7, self.height * 0.7
            pos: 0, 0
        Ellipse:
            size: self.width * 0.7, self.height * 0.7
            pos: self.width * 0.3, self.height * 0.3

        StencilUse:

        # 段階2: 段階1で決められた範囲制限のもと、描画が行われる
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            size: self.size
            pos: 0, 0

        StencilUnUse:

        # 段階3: ここでは段階1と全く同じ描画を行わなければならない。正しく後始末する為にこの手順が必要らしいです。
        Rectangle:
            size: self.width * 0.7, self.height * 0.7
            pos: 0, 0
        Ellipse:
            size: self.width * 0.7, self.height * 0.7
            pos: self.width * 0.3, self.height * 0.3

        StencilPop:
''')

runTouchApp(root)

Screenshot at 2018-04-24 19-02-17.png

楕円と長方形の重なっている部分が描画範囲から外れています。多分段階1で奇数回描画されたPixelのみが段階2における描画可能な範囲になるのだと思います。

VertexInstruction

vertex_instruction.png

doc, src, Lineのsrc

VertexInstructionsourcetextureというpropertyを持っています。RectangleMesh等で何気なく使っていたこのpropertyはここで実装されたものでした。という事はLinePointにもTextureを貼り付けれるはずです。

LineへのTexture貼り付け

from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
RelativeLayout:
    canvas:
        Line:
            points:
                [
                0, 0,
                self.width / 3, self.height,
                self.width * 2 / 3, 0,
                self.width, self.height,
                ]
            width: 30
            source: 'python-logo.png'
''')

runTouchApp(root)

Screenshot at 2018-04-24 19-43-46.png

PointへのTexture貼り付け

from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
RelativeLayout:
    canvas:
        Point:
            points:
                [
                0, 0,
                self.width / 3, self.height,
                self.width * 2 / 3, 0,
                self.width, self.height,
                ]
            pointsize: 100
            source: 'python-logo.png'
''')

runTouchApp(root)

Screenshot at 2018-04-24 19-51-07.png
簡易な粒子表現に使えそうです。

図形の塗りつぶし と 線の描画

通常長方形で塗りつぶす時はRectangleを使い、辺のみを書きたい時にはLineを使う事になると思います。この時のパラメータの渡し方が異なっていて非常にややこしいのでメモしておきます。

長方形

長方形の塗りつぶし
Rectangle:
    pos: self.pos
    size: self.size
長方形の線だけ
Line:
    rectangle: [*self.pos, *self.size, ]  # python3.5以降じゃないと使えない構文

楕円

楕円の塗りつぶし1
Ellipse:
    pos: self.pos
    size: self.size
楕円の線だけ1
Line:
    ellipse: [*self.pos, *self.size, ]
楕円の塗りつぶし2(扇型)
Ellipse:
    pos: self.pos
    size: self.size
    angle_start: 0
    angle_end: 270
楕円の線だけ2(扇型)
Line:
    ellipse: [*self.pos, *self.size, 0, 270, ]

角の丸い長方形

角の丸い長方形の塗りつぶし1
RoundedRectangle:
    pos: self.pos
    size: self.size
    radius: [30, ]
角の丸い長方形の線だけ1
Line:
    rounded_rectangle: [*self.pos, *self.size, 30, ]
角の丸い長方形の塗りつぶし2
RoundedRectangle:
    pos: self.pos
    size: self.size
    radius: [(10, 10), (40, 40), (100, 100), (200, 200), ]
角の丸い長方形の線だけ2
Line:
    rounded_rectangle: [*self.pos, *self.size, 200, 100, 40, 10, ]  # 注意: radiusの部分の順番と形式が異なる

真円

真円の塗りつぶし
真円に特化した塗りつぶし命令は無いのでEllipseで代用する
真円の線だけ1
Line:
    circle: [*self.center, min(*self.size) / 2]
真円の線だけ2(扇型)
Line:
    circle: [*self.center, min(*self.size) / 2, 0, 270]

Quadは四角形を描く命令です。Mesh別の記事で取り扱った事があるので割愛します。

ContextInstruction

context_instruction.png

doc, doc, src
自分でShaderを書かないのならContextInstructionの中で使う物は Scale, Rotate, Translate, Color, PushMatrix, PopMatrix の6つだけになると思います。この内のColor以外の5つは行列を操作する命令で、詳しくは過去の記事にて書いたので割愛します。

Clear

ClearはInstructionの派生Classではありません。それどころかClassですらありません。これはKv言語のcanvas内でのみ使える特殊な描画命令です。

from kivy.lang import Builder
from kivy.app import runTouchApp


root = Builder.load_string(r'''
Label:
    text: 'TEST'
    canvas:
        Color:  # A
            rgb: 0, 1, 0  # A
        Clear:  # B
        Rectangle:
            size: self.size
            pos: self.pos
            texture: self.texture
''')


runTouchApp(root)

Screenshot at 2018-07-29 03-01-08.png

B行を消した場合の結果

Screenshot at 2018-07-29 03-06-44.png

ClearによってClearの前に追加された描画命令であるColor(A行)とLabelが元々持っていた描画命令が消されていた事が分かります。

13
10
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
13
10