Edited at

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

今IoTで注目されている、手のひらサイズのコンピューター「Raspberry Pi(通称RPi、ラズパイ)」が人気を浴びています。

ラズパイでプログラムを動かしたりするとき、そのほとんどはPythonでやっていることが多いようです。

そのとき、プログラムを作っていて「GUIが使いたい」と思うときはありませんか?

過去にも紹介されてきている、簡単なGUIをわずかなコードで作れるライブラリをご紹介します。


軽量ライブラリ「Tkinter」

簡単に扱えるものの中に「Tkinter」というライブラリがあります。

現在はQtなどが主流ですが、Tkinterはコードを難しくすることなくできるので、日経Linuxなどでも取り上げられています。


Tkinterが動作している様子。

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


Tkinterの導入

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

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

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

※2019/01/29追記:Ubuntuなどの有名ディストリビューションでは標準でインストールされていますので作業は不要です。

これで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

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

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

#メインウィンドウのタイトルを変更

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()

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

端末に「clicked」が出力されるはずです。

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

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

では、クリックしたときにメッセージを変えてみます。これを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、packメソッドを呼び出す

プログラムの最後には、最後に作った部品に対してmainloopメソッドを呼び出すようにする