Python
GUI
Python3
Tkinter

Pythonで簡単なGUIを作れる「Tkinter」を使おう

今IoTで注目されている、手のひらサイズのコンピューター「Raspberry Pi(通称RPi、ラズパイ)」が人気を浴びています。
ラズパイでプログラムを動かしたりするとき、そのほとんどはPythonでやっていることが多いようです。
そのとき、プログラムを作っていて「GUIが使いたい」と思うときはありませんか?
過去にも紹介されてきている、簡単なGUIをわずかなコードで作れるライブラリをご紹介します。

軽量ライブラリ「Tkinter」

簡単に扱えるものの中に「Tkinter」というライブラリがあります。
現在はQtなどが主流ですが、Tkinterはコードを難しくすることなくできるので、日経Linuxなどでも取り上げられています。
tkinter-window.png

Tkinterが動作している様子。

さっそく導入してみましょう。

Tkinterの導入

まず、TkinterはPythonで動くので、まだインストールしていない場合はインストールします。

$ sudo apt-get install python python3 python-pip python3-pip

※python-pip、python3-pipは導入されていない場合があるので、Python導入済みでもインストールしてください。

これで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()メソッドで新しくウィンドウを作ります。

tk.py
# メインウィンドウ作成
root = tk.Tk()

とりあえずこれを書いた状態で実行してみましょう。これはtk.pyとして保存した場合です。

$ python3 tk.py

すると、プログラムが正しければ、何もないウィンドウが表示されるはずです。
キャプチャ.PNG

ちなみに、ウィンドウのタイトルを変えることもできます。

#メインウィンドウのタイトルを変更
root.title("Tkinter test")

キャプチャ.PNG

root変数で、Tkメソッドで作ったウィンドウが操作できるようになります。
root変数に対して、titleメソッドを呼び出すと、タイトルが変えられるというわけです。
日本語も入れられます。(※場合によっては文字化けするかもしれません)

今の状態では、ちょっとウィンドウサイズが小さいですね。大きくしてみましょう。
ウィンドウサイズを変えるには、geometryメソッドで変更できます。
例えば、640x480のウィンドウにするには

#メインウィンドウを640x480にする
root.geometry("640x480")

とします。実行してみると、大きくなっているのがわかると思います。
キャプチャ.PNG

最後は必ず、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」と表示されるはずです。
キャプチャ.PNG

Labelメソッドの書式はこんな感じです。

label = tk.Label(window, param1=value, param2=value...)

windowにはラベルを表示させたいウィンドウの変数を、param1=valueの部分には色々なパラメーターを指定します。
「abc」と表示させたいなら

label = tk.Label(window, text="abc")

となります。他のパラメーターを指定することもできます。

部品を表示するにはgrid()

label.grid()ってなんだろうと思ったと思いますが、gridメソッドはすべての部品に備わっているものです。
gridメソッドを呼び出さないと部品は表示されません。
※Buttonはpackメソッドで表示するのが主流です

ボタンを表示する

ボタンを表示するには、Buttonという部品を使えば表示できます。

button = tk.Button(root, text="ボタン", command="pushed")
button.grid()

キャプチャ.PNG

tk.Buttonでは、commandに関数を指定すると、クリックした時に関数を呼び出すことができます。
例えば、pushedという関数を作り、クリックするとprint関数で「clicked」と表示するものとしましょう。

def pushed():
 print("clicked")

defというのは、自作関数を作るものです。

それで、ボタン作成時は

button = tk.Button(root, text="クリックしてね", command=pushed)
button.grid()

とします。実行して、ボタンをクリックしてみてください。

端末に「clicked」が出力されるはずです。
キャプチャ.PNG

さらに、ボタン作成後に表示するテキストを変更することもできます。

button["text"] = "変更したぜ"

キャプチャ.PNG

では、クリックしたときにメッセージを変えてみます。これをpushed関数に取り込んでみましょう。
pushed関数の定義の部分を

def pushed(self):

に変えます。
その下に

tk.py
[空白]self["text"] = "押されたよ"
[改行]

を入力します。
Pythonでは、インデント(空白やタブ)でまとまりを認識しているので、空白を開けないと

IndentationError: expected an indented block

というエラーになります。そのため、defifなどの複数行記述するものは、必ずインデントをつけるようにしましょう。
また、まとまりの終わりは改行を1回余計に加えることが重要です。

さて、ボタンを生成する側は

button = tk.Button(root, text="ボタン", command= lambda : pushed(button))
button.pack()

にします。
ここで、lambdaというのが出ますが、これはPythonでコールバックなどを指定するときに役立つ無名関数というものです。
詳しくは「python lambda」「python 無名関数」で調べてみてください。

それで、pushed(button)の部分ですが、button変数をpushed関数から操作できるように、pushed関数に渡しています。
pushed関数ではそれをselfという変数として受け取っています。

これまでの部品を生成するプログラム

tk.py
#!/usr/bin/python3
# -*- coding: utf8 -*-
import tkinter as tk

def pushed(self):
 self["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.pack()

#メインループ
root.mainloop()

大体、PythonとTkinterに慣れたでしょうか?
Tkinterは他にも使えることがたくさんあるので、調べてみてください。

まとめ

まずはじめに、tk.Tk()でメインウィンドウをつくる
部品を生成したら、gridメソッドを呼び出す
プログラムの最後には、最後に作った部品に対してmainloopメソッドを呼び出すようにする