前回の投稿までラベルとボタンを扱えるようになり,それらの書式(?)の設定方法などを学びました.今回はそれらの配置についてほんの少しだけ深く学びます.前回のボタンの配置の指定方法は座標をピクセル単位で指定していましたが,これはあまり賢明な設定方法ではないです.画面の大きさが一定の場合は問題なのですが,デバイスが変わり画面の大きさが変わってしまうとレイアウトが崩れる可能性があります.そのような問題に対処する「動的配置」というもの初歩をこの投稿で学びます.
今回習う内容はこちらの動画の部分になります.
これからのkivyの投稿ではそれ以前の投稿の内容をを習っていることを前提に話を進めたいと思います.それらの投稿は本投稿の下にあるタグの「Kivy」をクリックすると一覧が見れます.
下準備:前回の復習
前回の結果と同じところまで作成しておく.新しくフォルダを作成して.「kivy5.py」と「kvfile.kv」というからのファイルを作成しておきましょう.そしてそれぞれのファイルの中身を次のように作成しておきます.
from kivy.app import App from kivy.uix.label import Label from kivy.uix.widget import Widget class Widgets(Widget): pass class kvfile(App): def build(self): return Widgets() if __name__ == "__main__": kvfile().run()
# File name: kivy5.py <Widgets>: Button: size: 100,75 pos: 0,0 text: "Kivy" color: 0,1,0,1 font_size: 40 Button: size: 300,75 pos: 100,0 text: "2kome Botan" color: 1,0,0,1 font_size: 40
ウィジェット内のラベル,ボタンの共通設定
先ほど作成したkvファイルの中を見てみると,ボタンを2つ作成しているのですが,どちらもフォントのサイズは40で同じ設定になっています.ボタンごとにフォントの大きさを変えておくのなら別々で書いてもよいのですが,特にそのような制限がない場合はまとめて書くことでコードも短くなり変更も容易になります.ボタンやラベルの数が増えてくるとなお重要になってくるでしょう.このように一つのウィジェット中のボタン,ないしはラベルの設定をまとめておくことは,次のように簡単に設定できます.kvfileを次のように編集してみましょう.
# File name: kivy5.py <Button>: font_size: 40 <Widgets>: Button: size: 100,75 pos: 0,0 text: "Kivy" color: 0,1,0,1 Button: size: 300,75 pos: 100,0 text: "2kome Botan" color: 1,0,0,1
ハイライトした部分のように,ボタンの設定をウィジェット内部の実際のボタンの位置でなく外部に書くことで,グローバルな(=そのプログラム全体の)ボタンの設定ができます.このように変更しても先ほどと実行結果は変わりません.font_size だけでなく,size, pos, text も同様の設定が可能です.
ボタンの位置の動的配置
今まで説明してきたkivyプログラムは,ウィンドウの大きさを特に考慮に入れていない計算でした.これまでの実行結果にたいして,ウィンドウの大きさを大きくしたり小さくしたりする操作をしても違いは現れることはないでしょう.しかし,例えば次のような注文があったとします.
せっかくkivyで作ってるんだから,どんなデバイスで表示してもうまくいくようにしたいんだよなー.そうだね,メニューバーはどんなデバイスでも絶対上に置けるようにしたいな!!
ユーザーの使うデバイスが限定している場合はボタンの位置,つまりposのオプションをその大きさに合わせて書けばいいだけなので全く問題なのですが,デバイスがあれこれ変わってしまうとそうしていてはレイアウトが崩れてしまいます.この要求のように,画面の大きさが変化しても(=動いても=Dynamic になっても)その大きさに合わせてボタン一の設定も変わってくれるようにすることを「動的配置(Dynamic placement)」といいます.
では,このような設定を実際kivyでどうするのでしょうか.答えは,先ほどの下準備ができている状態からkvファイルにそのような設定を書けばよい,それだけです.先ほどのkvfile.kvを次のように編集してみましょう.
# File name: kivy5.py <Button>: font_size: 40 <Widgets>: Button: size: 100,75 pos: root.x, root.top - self.height text: "Kivy" color: 0,1,0,1 Button: size: 300,75 pos: 100,0 text: "2kome Botan" color: 1,0,0,1
kvファイルだけこのように変更して,pythonファイルはそのままで実行してみましょう.すると,次のような実行結果が得られるかと思います.
kvファイルに「root.x」と書くことで「今見ているウィジェットの一番左」という意味になります.「root」の部分が「今見ているウィジェット」という意味になっているのですが,なぜそうなっているかは公式ドキュメントのrootの説明を見ると次のように書いてあります.
Programming Guide » Kv language >> Rule context
root: refers to the base widget/template in the current rule
今の場合ですと,設定しているButtonは元をたどるとWidgetsというクラス(まぁ,「機能の集り」という意味でオッケー)の中にあります.Buttonの設定のところでrootと書いた場合にはこの元(root)のWidgetsを指すようになるのです.
前回の投稿でチラッと説明しましたが,kivyでは座標の扱いを学校で習う数学のグラフの第1象限に対応しています.なので,「xの基準(root.x)」と書いたときは一番左になるわけですね.次に「root.top」ですが,これもroot.xのときと同様に考えると,「ウィジェットのてっぺん」という意味になります.kivyの
最初のボタンのposのy座標は「root.top – self.height」となっていますが,この「self.height」はボタンの高さを表しています.「self」で今設定をしているボタンそれ自身を表し,「height」でそのボタンのheightというオプション(属性)を表しています.「self」についても先ほどの公式ドキュメントの場所に次のような説明が書いてあります.
Programming Guide » Kv language >> Rule context
self: always refer to the current widget
要するに今自分が設定しているクラス(機能)をselfとして参照できるのですね.
このself.heightをroot.topから引き算してあげないと,ボタンがウィンドウの上に隠れてしまい,結局このボタンが表示されなくなってしまいます.理由は「posで設定される座標の値は,設定しているボタン(もしくはラベル)の左下の位置を意味しているから」です.
この例の最初のボタンのように,rootやselfを使うことでウィンドウの大きさが変わっても自分が置きたい場所にボタンやラベルを置くことができます.