Kivy 超入門(4):ボタンを作成する,ウィジェットの作成

忙しくて少し時間があいてしまいましたが,前回に引き続き Kivy のチュートリアルを載せていきたいと思います.これまで習った内容は次に書いてある投稿達になります.

Kivy 超入門(1):インストールからHello, World! まで
Kivy 超入門(2):ウィンドウのレイアウト,入力フォーム
Kivy 超入門(3):レイアウトを簡単に調整する(kvファイル)

これまでは主に Label という機能を使い文字を表示することをメインとしてきました.これはただ文字を表示するだけの機能でしたね.しかし,これまでの知識だけを用いて作れるアプリは,ただ与えられた文字を表示するだけのものになります.これでは GUI アプリを作成したいというのに,ただの連絡帳しか作れません...ということで今回は,タイトルにあるとおり,クリックできるボタンを作ってみましょう.ちなみに,今までは Label, TextInputの2つのウィジェットを使えるようになったので,これで3つ目ですね.

注意していただきたいのは,「ボタンを作成する」ことがこの投稿での目標でして,「ボタンを押すと,コレコレこういうことをできるようにする」ではないです.ボタンを押したときの操作(反応)の設定はもっとのちほどになるので,悪しからず...「その機能が知りたいんだが」という方は,こちらのYoutubeへのリンクに進んでいただくと「ボタンを押すと画面を切り替える」という機能を作ることをしていますので,見ていただくとよろしいかと思います.あくまでも自分はこのシリーズでチュートリアル的に順番にやっているので,このような内容を先取りすることはせずに進めていこうと思います.







今回習う内容はこちら.

今回はこの動画の順に説明せず,ワンクッション挟もうと思います.自分がいろいろ試行錯誤した結果,上の動画のやり方は最終的に慣れた人でないとあまりよくできないと判断したので,まずは簡単にボタンを作る方法から始めたいと思います.

ボタンの作成:Button クラス

button クラスのインポート

じれったいですが,今一度復習しましょう.まずは最初に習った Hello, World! のプログラムを再度見直してみます.

from kivy.app import App
from kivy.uix.label import Label

class IntroKivy(App):
    def build(self):
        return Label(text="Hello, World!")

if __name__ == "__main__":
    IntroKivy().run()

さて,ここで学んだ文字を表示させる機能である Label とは何だったかというと,2行目で「from kivy.uix.label import Label」とすることで使えるようにした「kivy.uix.label」というクラス(機能)でした.これを踏まえると,ボタンを作る際にはそれに対応するようなkivyの機能を持ってきて使えばよいという勘が働きます.実際,kivyにはボタンを作成する機能(クラス)があり,それを持ってきさえすれば(import すれば)あとは利用するのみです.では,それをもってきて使ってみましょう.Button は次のようにインポートします.

from kivy.uix.button import Button

kivy.uix.button」というクラスがクリックできるボタンを表示させてくれます.

ボタンの作成

これを利用して一番シンプルなボタンを作るプログラムを組んでみましょう.Hello, World!のファイルと次のように書き換えてみてください.

from kivy.app import App
from kivy.uix.button import Button

class IntroKivy(App):
    def build(self):
        return Button(text="Hello, World!")

if __name__ == "__main__":
    IntroKivy().run()

import するものを label の代わりに button,そしてそれを使う部分(Label から Button に),この2か所を修正しただけですね.ではこれを実行してみましょう.次のようなウィンドウが出てくるかと思います.
kivy4_1
「…Hello, World! のときより背景の色が薄くなって,灰色になっただけじゃない?」「灰色にするなんて指示はした覚えないんだけど...」と早とちりしてはいけません.このウィンドウをクリックしてみましょう.するとクリックしている間は次の図のように青くなっているかと思います.
kivy4_2
この青くなっているときが「ボタンを押している」ということを表しています.ということで,めでたくボタンを作成する方法がわかりました!

動画で説明している方法

上のやり方と,動画でのやり方の違い

ボタンを一つ表示させるプログラムを作ることがこの投稿の目標だったので,ぶっちゃけもう終わりです.しかし,動画でやっている方法がよくわからないと気持ち悪い.ということで,こちらの方法についても触れたいと思います.

先ほど紹介したやり方と,上の動画のやり方の大きな違いは

  1. button クラスでなく,widget クラスを用いている
  2. kvファイルを用いている

の二点です.kvファイルについては前回の投稿でどのようなものなのかアバウトに説明したので,widget クラスが何者なのか分かれば動画の方法は理解できそうです.

widget クラス

じゃぁそのwidget クラスってなんぞ?という疑問が,出てきますが,それに対するkivy公式の答えとしては次のようになるでしょう(widget.py の中に書いてある内容).

Widget class
============
The :class:`Widget` class is the base class required for creating Widgets.

名前の通り「ウィジェットを作る際の,基本的クラス」としか説明していなくて,これからは何も新しいことわからなかったです...ここで諦めず,次に「そもそもウィジェットという言葉ってどういう意味?」という疑問を考えてみます.これに対する答えの一つとして Wikipedia より引用させていただきます.

ウィジェット (Widget)

  • グラフィカルユーザインタフェースを構成する部品要素、およびその集まり→ウィジェット (GUI)、ウィジェット・ツールキット。「window gadget」の合成語ともいわれている。
  • ページや画面に埋め込み可能なアプリケーション

「あはぁー,なんとなく使ってたけど,確かに言われるとそういう意味だな,知ってたわー」なるほど,そう考えると今まで作ってきた Hello, World! を表示させるプログラムは,「ウィンドウの中に,”Hello, World!”が中に書かれたLabelウィジェット」や「ウィンドウの中に,”Hello, World!”が中に書かれたButtonウィジェット」と理解することができるでしょう.

さらに注目していただきたい部分は「部品要素」という部分です.作りたいGUIプログラムが複雑なものになるほど,いくつかのパーツに分けて開発した方が効率がいいですが,そのパーツの塊もウィジェットと呼ぶわけですね.そうです,今回動画の方で説明している方法はこの部品要素を作成するといういみで,widgetクラスを利用しています.そして作るプログラムは「ウィンドウ>ウィジェット>ボタン」のような入れ子構造になっていると理解してもよいかと思います(あくまでも比喩です).

Widget クラスの利用:Hello, World!からStep by Step

下準備:kvファイルを用いた Hello, World! の作成

今回はkvファイルも活用するので,今回の勉強のため新しくフォルダ「kivy4」を用意して,中に「Botan_Tutorial.py」と「kvfile.kv」を作成しましょう(もちろん,作成段階でファイルの中身は空っぽでオッケー).そして,それぞれの中身を次のように書いてみましょう.前回とほぼ同じなので,順に見てくださった方はプログラムを理解していただけるでしょう.

from kivy.app import App
from kivy.uix.label import Label

class kvfile(App):
    def build(self):
        return Label()

if __name__ == "__main__":
    kvfile().run()
# File name: Botan_Tutorial.py

<Label>
    text: "Hello World!"

前回のから名前だけ変えた丸パクリじゃねえかとか言わない.そして Botan_Tutorial.py を実行すると,前回と同じく画面に Hello, World! が表示されましたね.ここまでが確認できましたら,今回の主題のボタンに話を進めたいと思います.

widgetクラスのimport,作成

それでは早速,先ほど説明した「部品要素をまとめてくれる」widgetクラスを使えるようにして使えるようにしてみましょう.まずはウィジェット機能をインポートしましょう.行頭あたりに次の行を追加しましょう.

from kivy.uix.widget import Widget

これで,Botan_Tutorial.py でwidgetクラスを使えるようになりました.次に,pythonファイルのimportの行のあとに新しく次のような部分を追加してみましょう.

class Widgets(Widget):
    pass

pythonの言語だけで書かれているので,慣れている方は説明する必要すらないかと思います.私はわからなかったので説明を書くと「Widgets」という名前で新しくクラスを作成しています(小文字のsに注意).かっこの中の(Widget)は,先ほど使えるようにしたWidgetを継承(新しく使ったWidgetsというクラスでも使えるように)しています.そのクラスの中身はpassとなっていますが,これはpythonで「何もしない」という意味です.あれ,せっかくWidgetsというクラスを作ったのに何もしないの?先に結論を言うと,何もしないのではなく,ただ「pyファイルに何も書いていない」というのが正解です.つまり,pyファイルにはあまり書きたくないので,Widgetsがどのようなクラスなのかも,後でまとめてkvファイルに書いてしまおう,という発想です.

そして,kvファイルはまだ変更を加えていないので,このままプログラムを動かしても何も変わりありません(そもそも新しく作ったWidgetsを動かしていない).

作成した Widgets を使ってみる(未完成)

では,作成した Widgets クラスを早速使ってみましょう.次のようなpythonファイルにしてみてください.この時点ではまだ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()

return するプログラムが新しく作成したWidgetsクラスになりましたね.さて,これを実行してみるとどうなるでしょう.Hello, World!現れず,ただ黒い画面が現れるだけでしょう.main で実行しているのは kvfile().run() ですが,その kvfile().run()はWidgetsをreturnしてくれます.そして,そのWidgetsの中身はpass何もしないということを言っているので,ただ画面が出てきて終わってしまうのです.

ということで,次にこのWidgetsというアプリをカスタマイズしましょう.

kvファイルで,作った Widgets の設定を変更(完成)

では,kvファイルのほうで,作った Widgets の設定を変更してみましょう.やあーっとボタンが出てきます.kvfile.kv を次のように作成してみてください.

# File name: Botan_Tutorial.py

<Widgets>:
    Button:
        size:   100,75
        pos:    0,0
        text:   "Kivy"
        font_size:  40
        color:  0,1,0,1

ここまでで今回の演習するプログラムは完成なので,実行して結果を見てみましょう.次のような結果が得られるかと思います.
kivy4_3
ウィンドウの左下に緑色で”Kivy”と書いてありますね.さらにこの”Kivy”という文字をクリックしてみましょう.すると次のように先ほど見たボタンと同じ振る舞いを見せてくれることがわかります.
kivy4_4

kvファイルの解説です.鍵括弧でくくった は,pythonファイルの中にあるWidgetsクラスのことを意味していて,「を設定したいです」という宣言になります.コロンで改行してインデントした部分からは「Widgets」の中身を記述しています.2行目のButtonというところで,Widgetsという名前のウィジェットの中にボタンを作る宣言をしています.「最初のやり方みたいに Button をインポートしてないけどいいんですか?」いいんです!クゥーこれが Widget クラスの便利なところです.理由は「widgetクラスはbuttonクラスを継承している」という言い方になります.

続けて,コロン+インデントをしてWidgetsの中に入れる部品をきめて,その設定を書いています.このkvファイルの場合「Widgets の中には,1つのButtonを置きます.そして,そのボタンの設定は,sizeが(100,75)で,posが(0,0)で…」といった具合です.

Buttonの設定(オプション)

では,このボタンについての設定の部分について少し見ていきます.

size

ボタンの大きさです.「size:幅,高さ」のように設定します.数字の単位はピクセルです.

pos

ウィンドウのなかのどの位置にボタンを作るか設定します.「pos:x座標,y座標」のように指定します.注意すべきは「ウィンドウの左下」の座標が(x,y)=(0,0)であることです(数学の座標系の第一象限をイメージしましょう).多くのGUI1アプリを作成する際には「ウィンドウの左上」の座標が(x,y)=(0,0)となっていて,xの値が増えるほど右に,yの値が増えるほど下に行くようになっているので,それとの違いに気を付けましょう.数字の単位はピクセルです.

text

Label のときと同じオプションで,ボタンの中にどのような文字を表示するか決めています.「text:”文字列”」で設定します.

font_size

ボタンの中に表示されるテキスト(つまりtextオプションで設定した文字)の大きさを指定します.「font_size:数値」のようにして使い,数値の単位はポイント(pt)です(公式の文章でフォントの大きさの単位が載っていなかったのですが,自分で調整してみると,どうやらptらしいということがわかりました).

color

ボタンの中の文字の色を指定できます.ボタンそれ自身(文字の背景)の色でないので注意しましょう.指定方法は「color:Red, Green, Blue, 不透明度」のように指定します.それぞれの値の最大値は1であることに注意しましょう(うっかりすると255と入れたくなる人もいるはず).

ボタンをもう一個作る

手っ取り早く,ボタンをもう一個作る

最後にボタンをもう一つ作ってみましょう.実はkvファイルに少しだけ追加すれば実現できちゃいます.早速コードを見てみましょう.kvfile.kvファイルに次の部分を足してみてください.

# File name: Botan_Tutorial.py

<Widgets>:
    Button:
        size:   100,75
        pos:    0,0
        text:   "Kivy"
        font_size:  40
        color:  0,1,0,1
    Button:
        size:   300,75
        pos:    100,0
        text:   "2kome Botan"
        color:  1,0,0,1
        font_size:  40

これを実行すると,確かに次のようにボタンが2つ作成されます.それぞれの設定の意味は,下の実行結果を見ていただくとより明確になるのではないのでしょうか?
kivy4_5

Widgetクラスを作り,kvファイルで作る利点

まず,Widgetクラスを用いたことで,ウィンドウ一面にボタンを表示せず,「ウィンドウの中にこれこれこういう大きさのボタンを作る」ということができるようになりました.とはいってもこれはpythonファイルの中にオプションとして書いてあればできなくはないので,大きな利点ではないのかもしれません.しかし,kvファイルに設定を書くことで,開発者からするとすっきりしたプログラムが書け,開発効率は断然上がるのではないかと思う.

開発効率という面からもう一つのメリットが見えてくる(というか,言い方を買えただけかもしれないが).作りたいGUIアプリが,アプリ内でページを移動したりできるものを作る際,ページごとにkvファイルを作れば,とても編集が楽である.新しいページを作りたいときも,kvファイルにそのページの内容を書くだけでpythonファイルに何も修正を加えることなく編集ができたりもする.

余談

私としても,最初に書いたButtonクラスを使うよりも,widgetクラスを用いてkvファイルの方でボタンを作成する方をおすすめしたいですね.複雑にならないので,私のように少し複雑だと心が折れる人にはこちらの方が向いていました.

長くなりましたが,これでボタンの作成法については終わりにしようと思います.読んでいただきありがとうございます!


Creating Apps in Kivy

このブログについて

IAtLeX です.ブログをはじめてさほど時間がたっていないので,未熟な内容が多々あるかと思いますが,それも時間が解決してくれるはず...Python系の記事を着々と充実させていきたいです.投稿主についてはこちらを参照してください.

このブログについて - http://iatlex.com/about_blog/

コメントを残す

*