ラベル GUI の投稿を表示しています。 すべての投稿を表示
ラベル GUI の投稿を表示しています。 すべての投稿を表示

kv 言語の書き方・使い方を学ぶ

Python3 マスターへの道:その7


 今回は、前回名前を出していた kv 言語についてです。プログラムを作る前に、理解しないといけないことが多そうですね。ですが、kv 言語を理解できれば、また一歩 Kivy で様々プログラムを作ることができるようになれますね。

 という事で、いくら書けても、ロードの仕方がわからなければ本末転倒。まずは、kv 言語のロードの方法から。


kv 言語をロードする


 ロードの仕方は3つあります。

1:クラス名とファイル名を揃える方法

 まず、その1つ目は、実は、前回、お話ししました。それが、App クラスのサブクラスの名前をファイル名に合わせることでした。つまり、kv 言語で書いた Test.kv をロードする場合には、TestApp というApp のサブクラスを作成して、実行しました。

 この方法の場合は、ただ名前を揃えて、同じディレクトリに入れただけで、build メソッドのオーバーライドを pass と表記して、ロードできました。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           pass


2:Builder.load_file を使う方法

 この方法では、まず Builder というクラスをインポートします。そして、その load_file メソッドを使って、kv ファイルをロードします。例えば、インポートする kv ファイルで build メソッドをオーバーライドしたい場合には、return の値に、2 行目を組み込むことで、表示する事で、同じ出力が期待できます。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           return Builder.load_file('path/file.kv')


3:Builder.load_string を使う方法

 最後の方法なのですが、この方法でも Builder というクラスをインポートする必要があります。基本的に、load_string メソッドでは、''' で囲まれている中に、kv 言語で表記する事でロードできます。方法は、以下です。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           return Builder.load_string('''
 5   STRING:
 6   ''')

 一見、kv 言語の位置に違和感はありますが、試してみたら、上のように、kv 言語の先頭が、インデントなしで、始まっていないと出力できませんでした。

 このように、kv 言語をロードする方法は色々、様々なサンプルコードを見てみても、使っている方法は、人によっても違うようです。

 しかし、私は、諸事情により、基本的には、3つ目の方法をとっていく方針です。事情というのは、私のパソコンでは、.kv のファイルを開く際に、多少手間がかかるという程度のことです。


kv 言語を学ぶ


 という事で、ロード方法はわかったところで、kv 言語について、詳しくみていきましょう。まず、前触れという事で、言っておきますと、私にとっては、かなり複雑で、理解するために、かなり時間を費やしました。主に、参考にさせてもらったサイトは、公式サイトこちらのサイトです。

 わからないままでも使えるのは確かです。以前の tkinter でも、そうだったのかもしれません。しかし、それでは、Python3 をマスターということには、なりませんよね。

 まず、kv 言語で重要になってくる、初心者を困らせる単語が、多々あります。

  • class ルール
  • root ルール
  • ウィジェット/子ウィジェット
  • ……(などなど)
 確かに、これを理解している人は、簡単かもしれませんが、正直にいって、私にはどれもわかりませんでした。英語の時間に、知らない単語が出てきて、頭がパンク……そんな状況です。

 しかし、その理由として、それらをある程度知っている前提としているのが、痛いところです。しかし、なんだかんだ、時間を費やせば、わかってくるものです。


ルール とは


 まずは、二つある class ルールと root ルールからです。ルールと付くからには、なんらかの決まりなのですが、これは、簡単に言えば、どのように表示するか(カスタマイズするか)を指定するものです。

 しかし、なぜそれが二つもあるのでしょうか?class ルールは、クラス全体にルールが反映されます。つまり、あるクラスの中に、三つのウィジェットが存在した場合、その三つが全て、そのルールに従うのです。

 対して、root ルールは、それぞれのウィジェットとその子ウィジェットにのみ反映されます。つまり、三つのウィジェットそれぞれに、それぞれの root ルールが存在するということになります。

 ここで、子ウィジェットなのですが、簡単に言えば、ウィジェットの中のウィジェットです。例えば、配置用のウィジェットで指定した位置に、ボタンやラベルのようなウィジェットを配置する場合は、それらが子ウィジェットとなります。

 そして、その表記を区別するために、class ルールは、<class 名>: のように、半角の山括弧と:(半角コロン)をつけ、root ルールの場合は、括弧なしの、root 名: のように、:半角コロンのみで、表記します。

 kv 言語を使用する場合としない場合を比べてみると、わかりやすいかもしれません。コード自体に特に意味はありません……まずは、kv 言語を使用しなかった場合をみていきましょう。

 1   # kv 言語を使用しない場合
 2   from kivy.app import App
 3   
 4   # 各ウィジェットをインポート
 5   from kivy.uix.widget import Widget
 6   from kivy.uix.boxlayout import BoxLayout
 7   from kivy.uix.label import Label
 8
 9   class MyApp(App):
10       def build(self):
11           # インスタンスの作成
12           root = Widget()
13           box = BoxLayout(orientation='vertical')
14           
15           # add_widget を使って、box に子ウィジェット(二つのラベル)を作成
16           box.add_widget(Label(text="Hello"))
17           box.add_widget(Label(text="World"))
18           
19           # さらに、box ウィジェットを root ウィジェットの子ウィジェットに
20           root.add_widget(box)
21           return root
22   
23   if __name__ == '__main__':
24       MyApp().run()


 ここでは、Widget というウィジェットを使っていますが、空のウィジェットという認識で構わないです。つまり、12 行目では、ただ root というウィジェットを入れるためのインスタンスを作成したということです。なので、いきなり root を FloatLayout のインスタンス化しても良いのです。

 次に、kv 言語を使った場合をみていきましょう。
 1   # kv 言語を使用しない場合
 2   from kivy.app import App
 3   
 4   # 各ウィジェットをインポート
 5   from kivy.uix.widget import Widget
 6   from kivy.uix.boxlayout import BoxLayout
 7   from kivy.uix.label import Label
 8
 9
10   # Widget を継承した MyWidgets クラスを作成
11   class MyWidgets(Widget):
12       pass
13
14   class MyApp(App):
15   
16       def build(self):
17           return MyWidgets()
18   
19   if __name__ == '__main__':
20       MyApp().run()

 my.kv ファイル内
<MyWidgets>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Hello"
        Label:
            text: "Hello"

 kv ファイル内をみてもらうと、MyWidgets クラスに対して、class ルールが適用されていますね。そして、BoxLayout と Label には、それぞれの root ルールが存在しています。

 kv 言語を使った場合の方が、視覚的にわかりやすいですね。しかし、どちらがいい、悪いということはありません。コードが長くなっていくにつれて、kv 言語の使用は便利になっていくかもしれませんね。

 ちなみに、どちらのコードを実行しても、下のように表示されます。




最後に


 個人的に、今回の kv 言語の理解は大変でした。知らない考え方に加えて、わからない言葉が多々、説明も少なく、調べに調べてこの結果です。英語と日本語、両方で調べることができるって意外と便利ですね。

 次回からは、実際のコードをみながら、どのように Kivy のコードが書かれているかを見ていきたいと思います。読んでいただきありがとうございます。

Kivy のチュートリアルコードから初心者が理解してみる

Python3 マスターへの道:その6


 前回、最後にお知らせしたように、今回からは、tkinter に変わって kivy を学んでいきたいと思います。ですが、お伝えしたように、当面の目的は、非公式『どうぶつしょうぎ』のプレイ盤を GUI で作成することです。


Kivy をインストールしてみる


 Kivy のインストールの仕方は様々あるようで、色々比べて調べましたが、Kivy 公式サイトにあるHomebrew で使った方法で、インストールしました。時間はかかりましたが、無事インストールできたと思います(自信はないなぁ……)。

 色々使ってみようと、まずは、実行テストのために、公式サイトにあるコードを実行してみました。

 1   import kivy
 2   kivy.require('1.11.1')
 3   
 4   from kivy.app import App
 5   from kivy.uix.label import Label
 6   
 7   class MyApp(App):
 8   
 9       def build(self):
10           return Label(text='Hello world')
11   
12   if __name__ == '__main__':
13       MyApp().run()

 しかし、ここで知ったのが、jupyter notebook では、この Kivy は処理できないと……(厳密には、できるが、対応しているわけではないらしい)とにかく、Xcode にコピペして、hello_world.py で保存。そして実行!

$ python3 hello_world.py


 ちゃんと表示されました!(ちなみに、壁紙は、MacOS を Catalina にアップデートしたという報告も込めて)

 しかし、まだガッツポーズはできません。なぜなら、私がしたのは、ただのコピペ。コードを理解しなければ、学習になってませんよね。


Kivy のコードを理解していく


 コードの意味。これが、公式ページに、わかりやすく載っていればいいのですが、もちろん、プログラミング初心者には、理解がなかなか難しい。誰かがこれについて書いていないかと調べてみるものの、やはり、初歩すぎるのか、説明が見つかりませんでした……

 ということで、ここからは私のコードの解釈で進めていきます。間違っていたら、教えてください! 絶対ですよ!

 とにかく、まずは、部分ごとに分けて理解していくしかありませんね。まずは、

 1   import kivy
 2   kivy.require('1.11.1')

 これは、わかりそうですね。kivy モジュールをインポートして、少なくても必要なバージョン数を指定したという事でしょう。しかし、このモジュール自体は、自分でコードを実行する中では、必要はなさそうですね。

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

 この2行では、二つのモジュールからインポートしているみたいですね:kivy.app モジュールkivy.uix.label モジュール。この2行以降は、これらに基づいているようなので、この二つのモジュールを理解していくことから始めましょう!


kivy.app モジュール


 このモジュールからは、App というクラスがインポートされています。このクラスは、アプリケーションを作成するもののように考えておきます。そして、13 行目にもあるのですが、App.run を実行することで、アプリケーションを実行できるのです。

 しかし、今回のコードでは、App.run ではなく、MyApp().run になっていますよね。これは、実は、7 行目で、MyApp に App が継承されているからです。つまり、MyApp が App のサブクラスということです。

 7   class MyApp(App):

 私自身もサブクラスを使う機会が少なかったので、忘れていましたが、サブクラスを作成すると、親クラスのメソッドなどはそのまま使えます。なので、13 行目のコードも理解できますね。

13       MyApp().run()

 また、サブクラスでは、親クラスのメソッド再定義することで、オーバーライドすることができるのです。そして、それが、まさに、9, 10 行目で build メソッドに行われています。

 9       def build(self):
10           return Label(text='Hello world')

 ちなみに、build メソッドは、アプリケーションが実行された時(.run メソッドが使用された際)、その最初に、一度実行されるもののようです。

 そして、オーバーライドされる前は、空のようです。実際に、App クラスのまま、実行してみましたが、ウィンドウが表示されただけでした。


 ここで、最後に重要なのが、今回の MyApp のように、サブクラスは App で名前が終わらないといけないことです。この理由は、サブクラス名に基づいて、そのサブクラスから App を除いた名義の kv ファイルを探すからです。

 なので、プログラムをクラスで分けて書くことで、本元がだらだらと長くなることを防ぐことができます。ちなみに、kv ファイルにおける書式を、kv 言語と呼びます。これについては、次回から学んでいきます。


kivy.uix.label モジュール


 こちらの kivy.uix.label モジュールは、ここでは、Lable というメソッドをインポートするために使われています。この Label メソッドは、機能的に、tkinter での Label メソッドに似ていますね。この使い方としては、10 行目のような、書き方のようです。

10'          Label(text='Hello world')

 書式の変更には、markup という機能を用いる事でできるみたいです。これは、html の書き方に似ていますね。例えば、Hello World に使ってみるとすると、

10'          Label(text='[color=FF0000]Hello[/color] [b]world[/b]', markup=True)

 といった形式のようです。これを実行すると、


 赤文字(#FF0000)の Hello と 太字の world が表示されましたね。最初にしては、上出来ですね。

 他にも、先ほど名前を出した kv 言語では、少し異なった書式になっています。しかし、これも次回から、書いていきたいと思います。


__name__ と '__main__' の関係性


 という事で、まだ最後に、理解ができていないチュートリアルのコードがありますよね。そうです。次の 12 行目です。

12   if __name__ == '__main__':

 if 文だからわかりそうですが、__name__ もわかりませんし、__main__ もなんだか……

 と、このサイトを主に読んで、理解がなんとかできました。ありがとうございます。

 まず、__name__ には、そのファイル自体を指しています。そして、'__main__' は実行されているスコープ名(メインスコープ名)を指します。なので、この二つが同じであるということは、そのファイルが実行されているということになりそうです。

 逆に、もし、あるファイルがただインポートされているだけなら、__name__ と実際に実行している '__main__' は一致しません。なので、インポートの際に、コードが実行されてしまうのを防ぐ役割として、この if 文は存在しているのです。

 なので、今回のように、この py ファイルを実行しているので、13 行目のアプリケーションの実行文はしっかり実行されていましたね。


最後に

このように、今回は、kivy 初回にもかかわらず、なかなか濃厚な学習でしたね。tkinter と同じ GUI のシステムでも、根本的に違うことがわかりました。これからは、似たところも増えるのかな?

 Kivy のわかりやすい情報は、限られているので、実際にコードを書く前に、今回のように、現存するコードを理解していくところから、初めていきたいと思っています。説明がうまく伝わっていると嬉しいです。

 次回は kv 言語についても触れていきます。それでは、また!

前回:Tkinter フレームの使い方のウィジェットの構図を考える
次回:kv 言語の書き方・使い方を学ぶ

Tkinter フレームの使い方のウィジェットの構図を考える

Python3 マスターへの道:その5


 前回はウィジェットについて学びましたね。そうすることで、ついに、非公式『どうぶつしょうぎ』盤面の表示に成功しました。ですが、まだまだ、将棋を指すのには、程遠いですね。ですが、一緒に頑張っていきましょう!

プレイ画面の構図


 将棋を動かせるようにする前に、今現在私が考えている画面の構図を考えていきます。これによって、どうやって動かすのか、なども重要になってきますね。

  現在、私が考えている操作方法として、将棋の駒(ボタン)をクリックすると、下画面の矢印が可能な移動方向のみ、表示されます。そして、その移動方向の矢印(ボタン)を押すことで、移動ができるようにする、という仕組みです。



 画面は、上のようにしてみてはどうでしょうか? 持ち駒を置く場所も必要ですし、投了やプレイ終了などのボタンも必要になってきますよね。

 ですが、ここでわかるのが、ウィジェットごとに分かれていることです。これは、.place() を使ってしまえば、容易に配置できますが、実際に pixel 数を数えるのは面倒です。ウィジェットごとにまとまりが作れたら便利ですよね。

Tkinter:フレーム(Frame)の使い方


 しかし、まさに、そのために、tkinter にはフレーム(Frame)が存在します。今言ったように、これはウィジェットのまとまりです。なので、ウィンドウ上に、フレームを配置すること。そして、フレーム上に、ウィジェットを配置することで、上のような画面は可能になってくるのでは、ないでしょうか。それでは、早速、学んでいきましょう!

 意外にも、フレームの使い方はシンプルです。まずは、コードをみてみましょう。

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   
 6   #今回の新要素
 7   frame=tk.Frame()
 8   widget_name = tk.Widget(frame)
 9
10   root.mainloop()


 かなりシンプルですよね。フレームを作る際には、tk.Frame() を用いて、フレームの中に、ウィジェットを配置する際には、今まで、root と書いていた、Widget() の一番最初に、frame を書けばいいのです。

 そして、フレームは表示する際にも、その3で学んだ位置指定のメソッドを使えばいいのです。ちなみに、フレーム内に、ウィジェットを配置する際には、ウィジェットの左上の角が基準点になっているので、あくまで、今までのウィンドウの役割を、小さなフレームが補っているという考え方で正しいのです。

 それでは、上の画像のようなウィンドウを作成してみましょう。



 多少違いはありますが、似たようにできました。しかし、実はこのコードは紹介することができません。そして、それが次のお知らせに繋がっています……

重大なお知らせ


 実は、薄々気が付いていたのですが、私のやり方が悪いのか、システム上なのか、私の MacBook 上では、様々な Tkinter 機能が制限されています。ボタンの配色を変えたり、フレームの背景色を変えるなど、重要にも思えることが、どうにも調べてもわかりませんでした。
 なので、実は、上に表示した画像は、フレームごとに背景の配色がしてあるわけではなく、.place() で座標で色分けしています。実際、フレームは機能しているようで、色がなくても、しっかりと、ボタンなどは分かれて表示されているのですが、この不自由さが、たまらなく、辛く、これからもこの Tkinter を続けていくのが、億劫になってしまいました。

 そうして、調べた結果、今後は、Tkinter ではなく、Kivy を学んでいきたいと思っています。ちなみに、Kivy の場合だと(Tkinter でもできるかもしれないが)、スマホの画面にアプリのように表示させることなどもできるようなので、期待が大きいです。

 一様、一通り GUI の使い方は学んでいるので、今まで学んだことを無駄にせず、次のステップに向かっていきたいと思っています。これからも、非公式『どうぶつしょうぎ』は扱っていきます。今後ども、応援お願いします。

前回:tk.Label と tk.Button で画像を表示する
次回:Kivy のチュートリアルコードから初心者が理解してみる

tk.Label と tk.Button で画像を表示する

Python3 マスターへの道:その4


 第4回ということで、ウィジェットについて学んでいきたいと思います。これで、ただの真っ白なウィンドウからは、おさらばです!(前回はあくまで、位置指定のメソッドの学習のためでしたからね。)

 今回学ぶウィジェットでは、かなり私の目指している非公式『どうぶつしょうぎ』の盤面作成に近づくと思います!!

 1   import tkinter as tk
 2   
 3   root = tk.Tk()
 4     
 5   # 今回の新要素
 6   widget_name = tk.Widget(root)
 7   widget_name["option"] = "Choice"
 8   
 9   widget_name.pack()
10
11   root.mainloop()


Tkinter: ウィジェットの使い方


 前回は、配置位置の紹介として、あるウィジェットを使用していました。ウィジェッそうでは、tk.Label() メソッドでしたよね? しかし、ウィジェットは tk.Label() だけではありません。そのウィジェットの作成は、一般的には下記のように表示させます。

 6   widget_name = tk.Widget(root)

新ウィジェット:tk.Label メソッド


 ちなみに、前回の tk.Label() メソッドはこのように、使用されていましたね。
 6'  label = tk.Label(root)
このように、文字を表示していました。しかし、これだけでは、label という名前のウィジェットを作成しただけです。実際に文字を表示させる、文字の色を変える、画像を表示させる。そういったことを行うためには、オプションを使って、カスタマイズする必要があるのです。

 7   widget["option"] = "Choice"
上のように、オプションをウィジェットに加えることができます。オプションは、ウィジェットごとに様々あって、文字列のウィジェットなので、文字列の指定や、文字の色、背景の色などを変えることができます。例えば、下のように書くことができます。

 8   # 例
 9   widget["text"] = "String"   # 文字列の指定
10   widget["fg"] = "Color"   # 文字の色
11   widget["bg"] = "Color"   # 背景の色

 試しに、出力して見ましょう。黒い背景に白い文字で、"Suzuki Gakuto" なんてどうでしょうか?


うまくいきましたね。しかし、4行に分けて書くのは面倒ですね。実は、もっと短く、1文で、オプションを使いすることもできます。

 6'  widget = tk.Label(root, text = "String", fg = "Color", bg = "Color")

 簡単に短くなりましたね。また、特別読みにくかったりするわけでもないです。これからは、この書き方で書いていった方が良さそうですね。他のウィジェットも試してみましょうか?


新ウィジェット:tk.Button メソッド


 次のウィジェットは、ボタンです。よくクリックすると何かが起こる正体ですね。これが使えるようになれば、将棋盤への道へとまた一歩進むことになりそうです。しかし、使い方は、至ってシンプル。先ほどのウィジェットと同じです。
 6'  button = tk.Button(root)
 本当に同じですよね。そして、オプションの使い方ももちろん同じです。しかし、ウィジェットごとに、使えるウィジ ェットと使えないものがあるようです。

 例えば、ボタンに関しては、state というオプションを "disable" と下のように指定すればいいだけのようです。
 6'  button = tk.Button(root, state="disable")

 それでは、今回も使えるボタンと使えないボタンを並べて表示させてみます。



 使えないボタンは、薄くなって見えにくくなりましたね。実は、ボタンには、他にも、command というオプションがあります。そして、これは、ボタンを押した際に何が起こるか指定するもののようです。今後も使っていきたいですね。


新オプション:画像を表示させる


 これまで、文字とボタンのウィジェットを学びましたが、『どうぶつしょうぎ』の駒を表示するには、画像を使いたいですよね。なので、画像を表示できるようになる必要になりそうです。しかし、これが意外とシンプル……というわけには、いかなかったです。

 コードを書いてしまうと……

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   
 6   img = Image.open('path')
 7   photo = ImageTk.PhotoImage(img, master=root)
 8   pieces = tk.Button(root, image=photo)
 9   pieces.image = photo
10   
11   pieces.pack()
12   
13   root.mainloop()

 まずは、Image.open() で画像を収得、そして ImageTk.PhotoImage で画像を tkinter の理解できる形にして、pieces にボタンのウィジェットとして入れる。ということでしょうか……

 ですが、master = root とpieces.image = photo の二つが何か引っかかりますね。しかし、それがないとうまく画像が表示されなかったので、入れておきます。よかったらコメントで、説明してもらえると嬉しいです。

 ちなみに、画像は、こちらから拝借しました。それでは、表示させてみましょう。


 ちゃんと、表示できましたね。ボタンとして表示したので、もちろんクリックすることもできます。ですが、command は設定していないので、何も起こるわけはないですね。しかし、これも第一歩です!


非公式『どうぶつしょうぎ』最初の盤面


 それでは、command 関係なくなら、最初の盤面を表示させることができそうだということには気がつきましたか? 前回学んだ .grid() を使うことで、盤面のマス目のように、位置を指定すれば良さそうです。画像たちは、それぞれ駒ごとにサイズを変更してっと。

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   root.title("animal_chess")
 6   
 7   ''' 省略 piece: BH(ヒヨコ下), BL(ライオン下), BG(キリン下), BE(ゾウ下)
 8    TH(ヒヨコ上), TL(ライオン上), TG(キリン上), TE(ゾウ上)'''
 9   img = Image.open('path')
10   photo = ImageTk.PhotoImage(img, master=root)
11   piece = tk.Button(root, image=photo)
12   piece.image = photo
13   
14   #駒の配置
15   BH.grid(row=2,column=1)
16   BL.grid(row=3,column=1)
17   BG.grid(row=3,column=2)
18   BE.grid(row=3,column=0)
19   TH.grid(row=1,column=1)
20   TL.grid(row=0,column=1)
21   TG.grid(row=0,column=0)
22   TE.grid(row=0,column=2)
23   
24   root.mainloop()

 出力してみましょう。



 表示できました! まだ何も動かすことは、できませんが、あのノロノロと進んでいたのが、嘘みたいです。ちょっと突っ走ってしまいましたかね……


最後に


 このように、今回は、最初の盤面を表示させるまでに至りました。凄い進歩だと自分でも思ってしまいます。しかし、何も動かせなければ意味がありませんよね。次は、どのような構図にしていくかを考えながら、ウィジェットのまとまりであるフレーム(Frame)について学びたいと思います。

 意外と、このフレームがどこにも使われていることがあって、わからなくて困っていました。しかし、今度は私が学んで使う番ですね。次回をお待ちください!

前回:Tkinter の配置用メソッド .pack() .gird() .place()
次回:Tkinter フレームの使い方のウィジェットの構図を考える

Tkinter の配置用メソッド .pack() .gird() .place()

 Python3 マスターへの道:その3


  第3回ということで、今回は、ウィンドウに何か(ウィジェット)を表示したい、のですが……実は、今のままでは、表示できません。まずは、ウィジェットの位置を指定するメソッドを学ぶ必要があるのです。

 ですが、何も表示しないで、位置が指定できるわけではありません。なので、今回は、tk.Lable() で作ったウィジェットを使いながら、配置する位置の指定の基本を学んでいきます。

 ウィジェットの詳しい使い方は、次回『Python3 マスターへの道:その4』で学んでいこうと思うので、ここでは、ウィジェットという表示するものとして、認識しておきます。

1    import tkinter as tk
2    
3    root = tk.Tk()
4    
5    widget = tk.Label()
6    # 今回の新要素
7    widget.pack()
8    widget.grid()
9    widget.place(x=Number, y=Number)
10
11   root.mainloop()

 その位置を指定するために、必要なのが、.pack() と .grid() そして .place() の3つのメソッドたちです。これらのメソッドの学習には、こちらのサイト(全体的)こちらのサイト(.pack() を特に)を参考にさせてもらいました。


ウィジェットの位置の指定するために


 .pack() メソッド


7    widget.pack()

 これが、一番基本的なウィジェットの位置を指定できる、メソッドです。とりあえず、表示したいなら、これをウィジェットを作った後に、書けばいいだけです。デフォルトだと、上の中央に表示されます。





 ですが、表示したい位置もありますし、大きさとかも変えたい時もあるかもしれません。そんな時のための、オプションが、いくつかあります。実際に使って、表示させてみます。

 .pack(fill = 'x', padx = 10, pady = 5) で出力!fill は、横いっぱい('x')、縦いっぱい('y')に、ウィジェットを広げるオプション。padx と pady は、外枠からの余白を表しています。



 .pack(ipadx = 10, ipady = 5) で出力した場合。ipadx と ipady は、内枠からの余白です。わかりにくいですが、一番最初の、.pack() のみの出力と見比べてもらうと、枠のより中央に位置している感覚ですかね。↓




 複数を連続させて、.pack(fill = 'x') で表示させてみると……↓



 縦一列に表示されます。これは、つまり、デフォルトが、side = 'top' であるということです。つまり、横一列に表示したいなら、side = 'left' とかっこの中に、入れるだけで、次のように表示できます。ちなみに、fill は縦('y')でも使えます。↓



 では、横と縦を組み合わせて表示することはできるのでしょうか? ということで、4つのウィジェットを順番に、side = 'top', 'top', 'left', 'top' で試してみます。狙っているのは、右半分が、上と下で分かれたような、配置なのですが……↓




 おぉ、うまくいって……↓



 ないんですね。top やleft はどちら側に寄せているか、ということで、順番によって、ウィンドウが配置できているわけではありません。なので、横や縦一列に一次元方向に、配置する際には便利なのですが、二次元となると、それができないのです。

 それでは、二次元で配置する際は、どうすれば良いのでしょうか? それが、次の .grid() メソッドです。


 .grid() メソッド


8    widget.grid()

 ということで、.grid() では、二次元で配置ができるのですが、まずは、基本的な使い方から。かっこに何も入力しないで、出力してみると、左上の角に表示されました。↓




 複数個のウィジェットを、同時に、.grid() で表示してみると……↓




 先ほどとそれほど変わらないことがわかります。先ほどと大きく見た目が異なるのは、fill のオプションが使われていないためです。実際にいうと、fill というオプションは、.grid() にはないのです。

その代わりに、sticky というオプションがあります。これは、余裕があれば、fill のように広げる役割があるのですが、今後使いながら、確認していきたいと思います。

 しかし、まだ .gird() の凄さは伝わっていないでしょう。grid の最も大きい特徴は、文字通り、ウィンドウで表示する位置を、格子状に選択することができるのです。

8'   widget.grid(row = Number, column = Number)

 このコードをみてもらえば変わると思いますが、ここでは、配置場所を、縦の列と横の列を指定して、表示しています。そのため、ウィジェット同士の位置関係をはっきりとさせることができるのです。

 それでは、先ほど、.pack() では、できなかった二次元配列をしてみましょう。


 四色を2x2で並べたい時には、それぞれ (0, 0) (1, 0) (0, 1) (1, 1) の順番で、.grid() メソッドを使っていきます。↓




 格子状のように、配置されていることがよくわかりますね。

 それでは、先ほど .pack() で失敗してしまった、横並びの最後の二つが、上下で分かれて表示するようにするには、どうすればいいのでしょうか?

 それには、また別のオプションが必要になります。いくつかの縦の列に表示する際には、rowspan を、横の列の場合は、columnspan を使います。使い方は、簡単。通常通り、row と column で選択する最初の枠を選択して、rowspan と columnspan で、その長さを選択します。

 例えば、次のコードを実行させると、狙った配置で表示できます。

1    import tkinter as tk
2    
3    root = tk.Tk()
4    root.title(".pack() practice")
5    
6    red = tk.Label(root, text = "red", bg = "red", fg = "white")
7    blue = tk.Label(root, text = "blue", bg = "blue", fg = "white")
8    green = tk.Label(root, text = "green", bg = "green")
9    yellow = tk.Label(root, text = "yellow", bg = "yellow")
10   
11   red.grid(row= 0, rowspan = 2, column = 0)
12   blue.grid(row = 1, rowspan = 2, column = 1)
13   green.grid(row = 0, column = 2)
14   yellow.grid(row = 1, column = 2)
15   
16   root.mainloop()




 まだまだ、オプションもあるのですが、今回は、あくまで確認程度に配置のためのメソッドを学んでいきます。それにして、.grid() が一番使いやすそうと、私は感じました。配置場所がはっきりしているので、.pack() よりも多少面倒ですが、確実です。


 .place() メソッド


 これまで、.pack() はウィンドの枠からの位置関係、.grid() はウィンドウの左上からの位置関係を用いて、表示してきました。ですが、ウィジェットを、ウィンドウの好きな場所に自由に表示させたい時には、面倒ですよね。

 ということで、.place() は狙ったところを確実に表示できるメソッドになります。

9    widget.place(x=Number, y=Number)

 このコードの場合は、それぞれ x 軸と y 軸方向に、ピクセル数を入れて、ウィンドウの狙ったいちに、表示できます。なので、二つのウィジェットを (x=10, y=20)、そして、(x=15, y=30) とすることで、次のように、部分的に重ねることもできます。↓




 また、絶対に、位置を設定しなければならないわけではなくて、相対的な位置に配置するオプションもあるみたいです。ですが、今回は、あくまで、さらっと確認。また、.place() メソッドは多用するようでは、まだなさそうなので、これで .place() メソッドについては、終わりです。


最後に


 このように、.pack() と .grid() そして .place() の三つの配置メソッドを学んでいきました。色々な配置の仕方がわかって、楽しんじゃいましたね。ですが、まだ現時点では、意味もない、文字列を表示させているだけ。

 ですが、まだまだウィジェットの種類はあります。なので、次回は、他のウィジェットを学びながら、色々と配置していけたらいいです。

 また、今回は、画像多いため、重くなったり、わかりにくかったりした場合はすみません。コードを打っている私はまだしも、説明が難しいですね。これからも頑張ります。


前回:Tkinter のウィンドウをカスタマイズする方法

次回:tk.Label と tk.Button で画像を表示する

Tkinter のウィンドウをカスタマイズする方法


Python3 マスターへの道:その2

 

Tkinter のウィンドウをカスタマイズする


 前回は、Tkinter をインポートして、ウィンドウを表示するところまで、学習しました。しかし、そのウィンドウは未だ空白、少しずつカスタマイズしていきたいところです。ということで、今回は、空白のウィンドウのカスタマイズして行きたいと思います。

1    import tkinter as tk
2    
3    root = tk.Tk()
4    
5    # 今回の新要素
6    root.title("New Title")
7    root.geometry("NumberxNumber+Number+Number")
8    root.minsize(width=Number, height=Number)
9    root.maxsize(width=Number, height=Number)
10   root.resizable(width=Ture/False, height=Ture/False)
11      
12   root.mainloop()

 今回の新要素は、.title() と .geometry()、.minsize()、.maxsize()、そして .resizable()という、5つのメソッドです。これらによって、ウィンドウがどのように表示されるのかをプログラミングしていくことができるのです。


新メソッド: .title()


6    root.title("New Title")

 このメソッドは至ってシンプル。ウィンドウに名前をつけることができるようになります。そして、コードもシンプル。.title() のかっこの中に、つけたい名前を入れるだけ。絶対的な必要性はないかもしれませんが、わかりやすくする意味では、ささっとつけられるものになっています。

 このコードを実行すると、下のように出力されました。ちゃんと、ウィンドウの上に New Title になってますね。




新メソッド: .geometry()


ウィンドウの初期表示の大きさを設定


7'   root.geometry("NumberxNumber")
7'  root.geometry(width=Number, height=Number)

 このメソッドは、ウィンドウの初期表示の大きさを設定することができます。表示方法は上の二つ。どちらも出力は同じなので、1つ目の方が簡単に見えます。実際に、幅 x 高さ という形式で書いています。ですが、初見の人からしてみれば、2つ目は、幅と高さが一目でわかりますね。どちらで書きたいかは自分次第ってことですね。

 このコードを実際に、幅=300 pixel、高さ=500 pixel で実行してみると、しっかりと、下のように縦長のウィンドウが表示されましたね。




 ちなみに、二つ目の省略された方法で実行してみたら、高さと幅の順番が逆で、横長のウィンドウが……最初は面倒がらずに、一つ目の形式の方のように明白に表記した方がいいのかもしれません。


ウィンドウの初期表示の位置を設定


7''   root.geometry("+Number+Number")

 .geometry のメソッドは、ウィンドウの初期表示の位置を設定することもできます。そして、その方法は、パソコンの画面の左上からの距離(pixel)で表示されます。そして、数字の順番は、1つ目の数字は、画面の左からの距離、2つ目の数字は、画面の上からの距離になっています。

 ここで、マイナス(-)でも試したのですが、プラス(+)と同じように表示されました。また、Mac を使っているのですが、"+0+0" のように設定しても上のバーに被らないように表示されたので、上の一番角に表示することはできないようです。

 コードのカッコの中を (+300+600) のようにして、出力してみました。








※ウィンドウが見やすいように壁紙を変更しました。

 ここで、一つお願いです。初期表示の大きさを表示した際のように、明白に表示する方法がわからなかったので、一つしか表示してません。なので、知っている方はコメントください。


初期表示の大きさと位置を同時に設定


7    root.geometry("NumberxNumber+Number+Number")

 そして、二つを .geometry の二つの機能を組み合わせるようにして、上記のように表示できます。そして、カッコ内を (300x100+300+600) のようにして、実行してみると、先ほどのウィンドウの位置に、横長のウィンドウが表示されました。




新メソッド: .minsize() と .maxsize()


8    root.minsize(width=Number, height=Number)
8'   root.minsize("NumberxNumber")
9    root.maxsize(width=Number, height=Number)
9'   root.maxsize("NumberxNumber")

 そして、次のメソッドは、ユーザーがウィンドの大きさを変えることができる範囲を設定するものです。.minsize() で最小の大きさを、.maxsize() で最大の大きさを設定しています。これは、画像で表すのは難しいので、試してみるとわかります。

 これも、.geometry() のメソッドのように表記を二つの方法でできるので、基本を覚えておけば、すぐに使えます。ウィンドウ内で、大きさが小さすぎると問題がある際などに使うことになりそうですね。

 ここで、ユーザーが全くウィンドウの大きさを変えることができないようにするには、.geometry() で設定した幅と高さを、.minsize() と .maxsize() に設定すれば大丈夫そうです。しかし、面倒ですよね。そのために、次のメソッドがあります。


新メソッド: .resizable()


10   root.resizable(width=Ture/False, height=Ture/False)
10'  root.resizable(0/1, 0/1)

 そして、今回の最後の新しいメソッド、.resizable() です。これは、ユーザーがウィンドウの大きさを変更できないように設定することができます。そして、それは、False または 0 と設定することで、できます。ここでも、二つの表記がありますね。

 ですが、ここでは、2つ目の表記をした際に、どちらかの数字に 1 または True が含まれると、その方向のみに大きさが変更できるようになるのではなく、全体のウィンドウ自体の大きさが変えることができるようになってしまいます。

 なので、一方向のみの大きさを変えることを許可する場合は、先ほどのメソッドを使うしかなさそうです……

 カッコ内をどちらも 0 に設定して実行してみると、下のように、Mac のウィンドウの大きさを画面いっぱいにする、緑色のボタンの色が消えていることがわかります。これで、大きさが変更できなくなりましたね。




最後に


 このように、今回はウィンドウの表示をカスタマイズするための、5つのメソッドを学ぶことができました。ですが、まだウィンドウの中は空白のまま。次回は、ウィンドウに何かを表示させれればいいなぁ、と思っています。


前回:Python のモジュールのインポートの異なる方法と使い分け

次回:Tkinter の配置用メソッド .pack() .gird() .place()

Python のモジュールのインポートの異なる方法と使い分け


Python 3 マスターへの道:その1


Tkinter でウィンドウを表示する


 まずは、プレイ環境に必要な将棋盤を作っていくところから始めたいと思います。もちろん、私には、何の前知識もないので、こちらのサイトを参考にさせてもらいました。Tkinter という python3 の標準ライブラリに存在するパッケージを使ってみたいと思います。

 Tkinter については公式ページで、少し勉強してから使っていこうと思います。公式ページには、参考になるウェブサイトなどが添付されているので、積極的に使っていきます。


モジュールのインポート


 そうして、Tkinter について読んでいたのですが、いきなり引っかかってしまいました。それは、モジュールのインポートの仕方の基本についてです。実は、そこには主に4つの方法がありました。それら違いは、こちらから学ばせてもらいました。

1    import tkinter 

 まずは、tkinter が個別の名前空間としてインポートされます。これは、つまり、tkinter のメソッドやクラスを呼び出す際に、tkinter.メソッドや tkinter.クラスといった形で呼び出します。

2    import tkinter as tk

 次の、2つ目は、1つ目と同じく、個別の名前空間にインポートされます。ですが、ここでは as を使用することで、毎回 tkinter.メソッドや tkinter.クラスと書く代わりに、tk.メソッドや tk.クラスという形で呼び出すことができるようになります。

 なので、名前の長いモジュールの際や、なんども繰り返されるモジュールを使用する場合は、省略した名前で表記することで、効率的にコードを書くことができるのです。

3    from tkinter import ttk

 ここまでは、モジュール全体をインポートする形式でした。しかし、3つ目では、モジュールの中の特定のクラスやメソッドを呼び出す時に使用されます。また、1行目と2行目との大きな違いとして、個別の名前空間がないことが挙げられます。

 これは、つまり、既存していたクラスやメソッドと同一名のものがインポートされる時、それらは上書きされてしまうのです。

 しかし、利点として、tkinter.メソッドや tkinter.クラスのように、宣言しなくてよくなることが挙げられます。また、tkinter のライブラリの中から、どれが必要なのかをわかりやくすできることのようです。

4    from tkinter import *

 そして、4行目は、3行目の発展型で、ここでも、個別の名前空間が存在しないために、上書きが行われます。しかし、この場合は、モジュール全体を1行目や2行目のようにインポートしています。ですが、これは何が上書きされてしまったのか、把握が難しく、エラーを起こしやすいため、推奨しない場合が多いようです。

 ですが、色々、Tkinter の初心者向けのサイトを見てみると、4行目のように、インポートしている場合が、多いです。ですが、私は、推奨通りに、2行目の形式でインポートして行きたいと思います。

Tkinter のウィンドウを表示する


 それでは、まずは、Tkinter のウィンドウを表示するところから始めて行きます。コードは以下を使用しました。

1    import tkinter as tk
2    
3    root = tk.Tk()
4    root.mainloop()

 白紙のウィンドウが表示されました!



 結構シンプルにできました。ここでは、root というオブジェクトにTk クラスを割り当てています。そして、最後の .mainloop() は Tk クラスのメソッドを呼び出してます。この .mainloop() というメソッドは、イベントループと呼ばれるようです。イベントと処理を繰り返しているようで、真っ白の画面ですが、何からのイベントを待っているということになりますね。

 ですが、今回のウィンドウは形だけなので何も起こりません。今回は、ウィンドウを普通に閉じましたが、これからプログラムの中で、終了させたい際には、.destroy() というメソッドを使うことは覚えておかないといけないですね。

最後に


 今回は、インポートに時間をかけてしまって、全くと言っていいほど進展がありませんでした。それでも、コツコツ頑張って行きます。次回は、ウィンドウで何らかの表示を行うところまで行きたいですね。

 間違っている箇所や参考になった箇所があれば、コメントください!

※その6以降は、GUI を諸事情により、Tkinter から Kivy に移行しました。しかし、その5までの知識をある程度、ベースにはしているので、移行後はハイテンポで進んでいくと思います。なので、GUI の基本を知りたい方は、このまま読み進めてください。



前回:Python 脱初心者のために

次回:Tkinter のウィンドウをカスタマイズする方法