今IoTで注目されている、手のひらサイズのコンピューター「Raspberry Pi(通称RPi、ラズパイ)」が人気を浴びています。
ラズパイでプログラムを動かしたりするとき、そのほとんどはPythonでやっていることが多いようです。
そのとき、プログラムを作っていて「GUIが使いたい」と思うときはありませんか?
過去にも紹介されてきている、簡単なGUIをわずかなコードで作れるライブラリをご紹介します。
軽量ライブラリ「Tkinter」
簡単に扱えるものの中に「Tkinter」というライブラリがあります。
現在はQtなどが主流ですが、Tkinterはコードを難しくすることなくできるので、日経Linuxなどでも取り上げられています。
Tkinterが動作している様子。
さっそく導入してみましょう。
導入においては、以下の環境が必要です。
Name | Value |
---|---|
OS | Windows, macOS, Linux |
Pythonバージョン | 3.8以降 |
Tkinterの導入
まず、TkinterはPythonで動くので、まだインストールしていない場合はインストールします。
Windows の場合
WSLを使う手もありますが、TkinterはGUIを扱うものですのでネイティブ環境で実行します。
ここでは安定版の3.8.5をインストールします。
64ビット版: https://www.python.org/ftp/python/3.8.5/python-3.8.5-amd64.exe
32ビット版: https://www.python.org/ftp/python/3.8.5/python-3.8.5.exe
起動して最初の画面には「Add Python 3.8 to PATH」のチェックボックスがありますのでチェックを入れます。
これを設定すると、どこでもPythonが使えます。
まあ、本当はチェックボックス設けないで自動的にパス通してほしいのですが...
途中インストールを進めているとオプション機能をインストールするか尋ねられます。
Tkinterを使いますので、td/tk and IDLE にチェックを入れて進んでください。
最後にこの画面が出ますが、「Disable path length limit」というものがあります。
これは、環境変数に登録できるパスの長さを無制限にするものです。設定したからと言ってWindowsが起動しなくなったり不安定になることはありません。
特に事情がなければクリックして制限を外しておきます。
macOS の場合
こちらも公式サイトよりダウンロードできます。
前者同様、3.8.5をインストールします。
64ビット版: https://www.python.org/ftp/python/3.8.5/python-3.8.5-macosx10.9.pkg
Mac OS Xでは32ビット版はありません。
macOSのインストーラでは自動的にTkinterがインストールされますので特段操作は必要ありません。
画面の表示に従ってください。
Linux の場合
Ubuntu系ディストリビューションや、一部のLinuxOSでは、はじめからPythonがインストールされているものがあります。
事前に $ python3 --version
を実行して存在を確かめ、ないようであれば必要に応じてインストールしてください。
$ sudo apt-get install python3.8 python3-pip
※2020年7月30日追記 Python2.7のサポートが終了しましたので、インストールするパッケージを修正しました。
これでPythonは用意できました。次にTkinterをインストールします。
$ sudo apt-get install python3-tk
完了すればTkinterの準備は完了です。
Pythonで使えるようにするには
Pythonでは、ライブラリのインポートにimport
というのを使います。
例えば、timeというライブラリをインポートするにはimport time
とします。
カンマ区切りで一括で指定することもできます。
import os, sys, time
ここではTkinterをインポートするので、import tkinter
と入力します。
でも、毎回 tkinter.・・・とするのは面倒なので、tkという名前で使えるようにしたいなら
import tkinter as tk
と記述します。ここからは、tkというエイリアス名でプログラムを作成していきます。
では、GUIを作成していきます。
GUIを試しに作ってみよう
Tkinterでは、ボタンなどをウィジェットと呼んでいます。
でもいまいちピンと来ない方もいるでしょうから、ここでは部品と呼ぶことにします。
rootウィンドウを作る
Tkinterでは、まずrootウィンドウを作らないと、ウィンドウが表示されません。
また、色々な部品を表示するときにも、すべてrootウィンドウにぶら下がります。
そのため、Tk()メソッドで新しくウィンドウを作ります。
# メインウィンドウ作成
root = tk.Tk()
とりあえずこれを書いた状態で実行してみましょう。これはtk.pyとして保存した場合です。
$ python3 tk.py
すると、プログラムが正しければ、何もないウィンドウが表示されるはずです。
ちなみに、ウィンドウのタイトルを変えることもできます。
#メインウィンドウのタイトルを変更
root.title("Tkinter test")
root変数で、Tkメソッドで作ったウィンドウが操作できるようになります。
root変数に対して、titleメソッドを呼び出すと、タイトルが変えられるというわけです。
日本語も入れられます。(※場合によっては文字化けするかもしれません)
今の状態では、ちょっとウィンドウサイズが小さいですね。大きくしてみましょう。
ウィンドウサイズを変えるには、geometryメソッドで変更できます。
例えば、640x480のウィンドウにするには
#メインウィンドウを640x480にする
root.geometry("640x480")
とします。実行してみると、大きくなっているのがわかると思います。
最後は必ず、mainloop()
ウィンドウの表示ができるようになりましたが、最後にもう1つ。
Tkinterでは、各部品を表示した後は、最後に追加した部品でmainloopメソッドを実行することが定められています。
これがないと、ボタンなどが正しく表示されない、描画されない、イベントが処理されないといったバグの原因になります。
例えば、今rootウィンドウを作りましたが、とりあえずrootウィンドウだけなので、そちらでmainloopメソッドを呼び出します。
#rootを表示し無限ループ
root.mainloop()
このmainloopメソッドはどの部品でも必須です。覚えておきましょう。
テキストを表示する
TkinterではLabelという部品を使うと、文字を表示できます。
試しに「Hello,World」と表示してみましょう。
#ラベルを追加
label = tk.Label(root, text="Hello,World")
#表示
label.grid()
root.mainloop()
最後にroot.mainloop()
と書いてある場合は消してから追加してください。
実行すると、左上に「Hello,World」と表示されるはずです。
Labelメソッドの書式はこんな感じです。
label = tk.Label(window, param1=value, param2=value...)
windowにはラベルを表示させたいウィンドウの変数を、param1=valueの部分には色々なパラメーターを指定します。
「abc」と表示させたいなら
label = tk.Label(window, text="abc")
となります。他のパラメーターを指定することもできます。
部品を表示するにはgrid()
label.grid()ってなんだろうと思ったと思いますが、gridメソッドはすべての部品に備わっているものです。
pack、gridメソッドを呼び出さないと部品は表示されません。
※Buttonはgridメソッドで表示するのが主流です
ボタンを表示する
ボタンを表示するには、Buttonという部品を使えば表示できます。
button = tk.Button(root, text="ボタン", command=pushed)
button.grid()
tk.Buttonでは、commandに関数を指定すると、クリックした時に関数を呼び出すことができます。
例えば、pushedという関数を作り、クリックするとprint関数で「clicked」と表示するものとしましょう。
def pushed():
print("clicked")
defというのは、自作関数を作るものです。
それで、ボタン作成時は
button = tk.Button(root, text="クリックしてね", command=pushed)
button.grid()
とします。実行して、ボタンをクリックしてみてください。
さらに、ボタン作成後に表示するテキストを変更することもできます。
button["text"] = "変更したぜ"
では、クリックしたときにメッセージを変えてみます。これをpushed関数に取り込んでみましょう。
pushed関数の定義の部分を
def pushed(b):
に変えます。
その下に
[空白]b["text"] = "押されたよ"
[改行]
を入力します。
Pythonでは、**インデント(空白やタブ)**でまとまりを認識しているので、空白を開けないと
IndentationError: expected an indented block
というエラーになります。そのため、defやifなどの複数行記述するものは、必ずインデントをつけるようにしましょう。
また、まとまりの終わりは改行を1回余計に加えることが重要です。
さて、ボタンを生成する側は
button = tk.Button(root, text="ボタン", command=lambda: pushed(button))
button.grid()
にします。
ここで、lambdaというのが出ますが、これはPythonでコールバックなどを指定するときに役立つ無名関数というものです。
詳しくは「python lambda」「python 無名関数」で調べてみてください。
それで、pushed(button)
の部分ですが、button変数をpushed関数から操作できるように、pushed関数に渡しています。
pushed関数ではそれをbという変数として受け取っています。
これまでの部品を生成するプログラム
#!/usr/bin/python3
# -*- coding: utf8 -*-
import tkinter as tk
def pushed(b):
b["text"] = "押されたよ"
#rootウィンドウを作成
root = tk.Tk()
#rootウィンドウのタイトルを変える
root.title("Tkinterテスト")
#rootウィンドウの大きさを320x240に
root.geometry("320x240")
#Label部品を作る
label = tk.Label(root, text="Tkinterのテストです")
#表示する
label.grid()
#ボタンを作る
button = tk.Button(root, text="ボタン", command= lambda : pushed(button))
#表示
button.grid()
#メインループ
root.mainloop()
大体、PythonとTkinterに慣れたでしょうか?
Tkinterは他にも使えることがたくさんあるので、調べてみてください。
まとめ
まずはじめに、tk.Tk()でメインウィンドウをつくる
部品を生成したら、grid、packメソッドを呼び出す
プログラムの最後には、最後に作った部品に対してmainloopメソッドを呼び出すようにする