Python で Tkinter を使ってめちゃくちゃ簡単に GUI アプリを作る

tkinter解説ページのアイキャッt

最近 Python の勉強を始めました!

勉強に使っている参考書は下記のPythonでつくる ゲーム開発 入門講座です。

この本を読んで分かったのですが、Python では Tkinter を使うとめちゃくちゃ簡単に GUI アプリを作成することができます。

このページではこの Tkinter に対し、「どのようなものか?」「できることは?」「使い方は?」のあたりについて解説していきたいと思います。

動作確認環境

このページで紹介するサンプルスクリプトは下記環境で動作確認を行っています

  • OS:macOS Catalina
  • Python:3.8
  • Tkinter:8.6

Tkinter とは

Tkinter とは Python3 で GUI アプリケーションを開発ための標準ライブラリです。

標準ライブラリですので、Python3 本体をインストールするだけで Tkinter を利用することができます。

さらに様々な OS 上で動作しますので、Python さえインストールされていれば、同じ Python スクリプトで多くの環境で動作させることが可能です。

Tkinter でできること

Tkinter は GUI アプリケーションを開発するために必要なさまざまな機能を提供します。

  • GUI アプリを作成
  • キャンバスの作成や描画
  • ボタンやラベルの作成
  • キー入力の受付
  • タイマーの作成

スポンサーリンク

Tkinter の使い方(オブジェクトの作成と配置)

Tkinter は他のライブラリやモジュール同様に tkinter ライブラリをインポートすれば使用することができます。

tkinterのインポート
import tkinter

GUI アプリの作成

tkinter ライブラリの Tk クラスのオブジェクトを作成し、そのオブジェクトで mainloop メソッドを実行するだけで「何もしない」GUI アプリを作成することができます。

アプリの作成
# -*- coding:utf-8 -*-
import tkinter

# アプリの作成
app = tkinter.Tk()

# アプリの待機
app.mainloop()

作成されるアプリは下のようなものになります。

tkinterで作成されるGUIアプリ

さらに、mainloop メソッド実行前に、下記のように geometry メソッドによりアプリのウィンドウのサイズを、title メソッドによりアプリのウィンドウのタイトルを設定することもできます。

アプリウィンドウの設定
# アプリの画面設定
app.geometry(
    "400x400" # アプリ画面のサイズ
)
app.title(
    "アプリのタイトル" # アプリのタイトル
)

これによりアプリのウィンドウがメソッドに指定したパラメータに応じて変化します。

アプリのウィンドウ設定

今後様々な Tkinter の使用方法について解説しますが、基本的にこれは Tk クラスのオブジェクト生成後 〜 mainloop メソッド実行前の間に実行するようにしてください。

処理を記述する場所
# -*- coding:utf-8 -*-
import tkinter

# アプリの作成
app = tkinter.Tk()

##### 〜処理を記述する場所〜 #####

# アプリの待機
app.mainloop()

mainloop メソッドを実行するとアプリが待機状態になってしまいますので、mainloop メソッド実行の後ろに記載されている処理はアプリが終了しないと実行されません。

キャンバスの作成と配置・描画

またキャンバスを利用して図形を描画することも可能です。キャンバスとは絵などを描画するあのキャンバスです。

キャンバスに絵を描く様子

tkinter ライブラリの Canvas クラスのオブジェクトを作成することでキャンバスを作成することができます。

キャンバスの作成
# キャンバスの作成
canvas = tkinter.Canvas(
    app, # キャンバスの作成先アプリ
    width = 300, # キャンバスの横サイズ
    height = 300, # キャンバスの縦サイズ
    bg = "black" # キャンバスの色
)

さらに place メソッド(pack メソッドなどでも良い)によりアプリ上にキャンバスを配置することができます。

キャンバスの配置
# キャンバスの配置
canvas.place(
    x = 50, # キャンバスの配置先座標x
    y = 50 # キャンバスの配置先座標y
)

これらによりキャンバス(黒石キャンバス)が作成され、アプリ上に配置されます。

キャンバスの作成と配置

作成したキャンバスには create_rectangle 等のメソッドを使用して図形を描画することも可能です。

キャンバスへの描画
# キャンバスへの図形(長方形)描画
canvas.create_rectangle(
    40, 40, # 長方形のキャンバス上の始点座標
    260, 260, # 長方形のキャンバス上の終点座標
    outline = "white", # 枠線の色
    width = 5, # 枠線の太さ
    fill = "green" # 塗り潰しの色
)

描画結果は下の図のようになります。

キャンバスへの図形の描画

ラベルの作成と配置

ラベルも簡単に作成できます。

tkinter ライブラリの Label クラスのオブジェクトを作成することラベルを作成することができます。

またキャンバス同様に placepack メソッドによりアプリ上にボタンを配置することができます。

ラベルの作成と配置
# ラベルを作成
label = tkinter.Label(
    app, # ラベルの作成先アプリ
    font = ("System", 30), # ラベルのフォント
    text = "ラベルです" # ラベルに表示するテキスト
)
label.place(
    x = 50, # ラベルの配置先座標x
    y = 50, # ラベルの配置先座標y
)

ラベルを配置した結果は下のようになります。

ラベルの作成と配置

ボタンの作成と配置

ボタンの作成もキャンバスやラベルと同様にtkinter ライブラリの Button クラスのオブジェクトを作成することで実現できます。

またボタンの配置もキャンバスやラベル同様に placepack メソッドを利用して行います。

ボタンの作成と配置
# ボタンを作成
button = tkinter.Button(
    app, # ボタンの作成先アプリ
    text = "ボタン", # ボタンに表示するテキスト
)
# ボタンの配置
button.place(
    x = 100, # ボタンの配置先座標x
    y = 100, # ボタンの配置先座標y
)

Tkinter の使い方(イベントの受付)

先ほどボタンの作成と配置について説明しましたが、このボタンは単に「ボタンの形をしたもの」であり、クリックしても何も処理が行われません。

次はこのボタンをクリックした時に処理が行われるようにしていきたいと思います。

(前提知識)イベントとは

と、その前にまずはイベントについて説明します。イベントのことを既にご存知の方は次の節にスキップしてください。

イベントとはアプリ(プログラム)で発生した出来事(メッセージ・アクション・割り込みなど)のことを言います。

例えばイベントとして下記のようなものが挙げられます。

  • ボタンがクリックされた
  • キーボードが押された
  • マウスが動かされた
  • 一定時間が経過した

アプリによってはこれらのイベントが発生した時に、特定の処理を実行したい事があります。

例えば、下記のようなケースが考えられます。

  • 計算機アプリ:「=」ボタンがクリックされた時に計算結果を表示したい
  • RPGアプリ:「→」キーが押された時にキャラクターを右に移動したい
  • テトリスアプリ:一定時間経過したらブロックを一段階下に落としたい

これらのような事が行えるように、各プログラミング言語には「特定のイベントを受付け」、「そのイベント発生時に特定の処理(関数)を自動的に実行する」仕組みが備わっています。

ただし、これらの仕組みは OS 毎に利用方法が違ったりして使いにくい傾向にあります。

ただし、Tkinter を使うと簡単に、さらにいろんな OS で共通的にこのイベント処理を実現する事が可能です。

実際に、どのようにしてこのイベント処理を実現するかを、受け付けるイベント毎に解説していきたいと思います。

ボタンクリックのイベント受付

ボタンクリックのイベントを受け付けるのは非常に簡単です。

ボタンのオブジェクト作成時(つまり Button() 実行時)に引数 command を指定すれば良いだけです。

この command にボタンクリック時に実行したい関数名を指定れば、ボタンがクリックされた時にその指定した関数を実行することができます。

ボタンクリックのイベント受付
# ボタンを作成
button = tkinter.Button(
    app, # ボタンの作成先アプリ
    text = "ボタン", # ボタンに表示するテキスト
    command = click_func # ボタンクリック時に実行する関数
)
# ボタンの配置
button.place(
    x = 100, # ボタンの配置先座標x
    y = 100, # ボタンの配置先座標y
)

上記では引数 command に関数 click_func を指定しています。

click_func を下記のように定義してみましょう(labelラベルの作成と配置で作成したラベルを指します)。

ボタンクリック時に実行する関数
def click_func():
    global label
    # ラベルの表示テキストを変更
    label[ "text"] = "クリックされました"

まず Python スクリプトを実行すると下のような画面が表示されます。ボタンが表示されていることが確認できると思います。

ボタンの作成と配置

ここでボタンをクリックすると、画面が下のように変化します。

ボタンクリックイベントの受付

Button() に引数 command を指定する事で、ボタンクリックのイベントを受け付けるようになります。

さらに、その引数 commandclick_func 関数を指定した事で、ボタンクリックが実際に行われた際に click_func が実行されるようになります。

これにより、ボタンがクリックされると click_func 内でラベルの text が変化し、それに伴いラベルに表示されるテキストが変化するようになりました。

こんな感じでアプリに対するイベントの受付とそのイベントに対する処理を簡単に実行することができるのも Tkinter の特徴の1つです。

キー入力イベントの受付

まずはキーボード関連のイベントの受付を行う方法について解説します。

キーボードの押し下げイベントの受付

キーボードが押し下げられたイベントを受け付けるためには Tk クラスのオブジェクト app を用いて下記のように bind メソッドを実行します。

キーボードの押し下げイベント受付
app.bind(
    "<Key>", # 受付けるイベント
    press_key_func # そのイベント時に実行する関数
)

"<Key>" の部分は "<KeyPress>"にしても良いです。

第2引数にはキーボードが押し下げられた時に実行したい関数を指定します。

mainloop メソッド実行前に bind メソッドを実行する事で、キーボードの押し下げイベントを受け付けるようになり、実際にキーボードの押し下げが行われたしには指定した関数が実行されるようになります。

例えばキーボード押し下げ時に実行する関数は下記のように定義します。

キーボード押し下げ時に実行する関数
def press_key_func(event):
    global label
    # 入力されたキーを取得
    key = event.keysym

    # 入力されたキーに応じてラベルを変更
    if key == "Left":
        label[ "text" ] = "左が押されました"
    elif key == "Right":
        label[ "text" ] = "右が押されました"

ポイントは引数です。

bind メソッドでイベントの受け付けを行うようにした場合、そのイベント発生時に実行される関数では、発生したイベントの情報が格納されるように引数を1つ指定する必要があります。

この引数から発生したイベントが具体的にどのようなものであるかを把握する事ができます。 

例えば上の例では引数 eventkeysym メンバから、どのキーが押し下げされたのかを取得し、そのキーに応じて処理を切り替えるようにしています。

上記のように press_key_func を定義し、bind メソッドを実行するようにすれば、「→」キーか「←」キーが押された際にラベルに表示される文字列が変化するようになります。

キーボード押し下げのイベント受付

bind メソッドによりイベント受付を行うようにしたイベントは、unbind メソッドによりキャンセルすることも可能です。

bind のキャンセル
app.unbind(
    "<Key>" # 受付をキャンセルしたいイベント
)

キーボードが離されたイベントの受付

キーボードが離されたイベントを受け付けるためには、押し下げ時同様に Tk クラスのオブジェクト app を用いて下記のように bind メソッドを実行します。

キーボードが離されたイベント受付
app.bind(
    "<KeyRelease>", # 受付けるイベント
    release_key_func # そのイベント時に実行する関数
)

受け付けるイベントが "<KeyRelease>" に変わった点がポイントです。これにより、キーボードが離されたイベントを受け付けるようになります。

さらに実際にキーボードが離された際には release_key_func が実行されます。

特定のキーの押し下げイベントの受付

下記のように bind メソッドを実行すれば、特定のキーの押し下げのみのイベントを受け付けるようになります。

左キーの押し下げイベント受付
app.bind(
    "<Left>", # 受付けるイベント
    press_key_func # そのイベント時に実行する関数
)

上の例だと左キーが押された時のみ press_key_func が実行されるようになります。bind メソッドを複数実行する事で、複数のキーの押し下げのイベントを受け付け、それぞれ別の関数を実行することも可能です。

左キーと上キーの押し下げイベント受付
app.bind(
    "<Left>", # 受付けるイベント
    press_left_func # そのイベント時に実行する関数
)
app.bind(
    "<Up>", # 受付けるイベント
    press_up_func # そのイベント時に実行する関数
)

マウスイベントの受付

マウスイベントもキーボードイベント受け付けと同様に bind メソッドの実行により実現する事ができます。

イベント発生時に実行する関数もキーボード同様に、第1引数にはイベントの詳細が格納されます。

例えば xy メンバを使用してマウスのクリック位置やマウスボタンが離された位置に応じた処理を行うことも可能です。

マウスの移動イベントの受付

マウスの移動イベントを受け付けるためには、bind メソッドの第1引数に "<Motion>" を指定します。

マウス移動イベントの受付
app.bind(
    "<Motion>", # 受付けるイベント
    mouse_move_func # そのイベント時に実行する関数
)

マウスボタンのクリックイベントの受付

マウスのクリックイベントを受け付けるためには、bind メソッドの第1引数に "<BottunPress>" もしくは "<Bottun>" を指定します。

マウスクリックイベントの受付
app.bind(
    "<BottunPress>", # 受付けるイベント
    mouse_click_func # そのイベント時に実行する関数
)

マウスボタンを離すイベントの受付

マウスの移動イベントを受け付けるためには、bind メソッドの第1引数に "<ButtonRelease>" を指定します。

マウスボタンを離すイベントの受付
app.bind(
    "<ButtonRelease>", # 受付けるイベント
    mouse_release_func # そのイベント時に実行する関数
)

タイマーイベントの受付

イベント受付の例として最後にタイマーイベントについて解説します。

Tkinter には指定した時間が経過したことをイベントとして受け付け、実際に時間が経過した際に指定された関数を実行する仕組みがあります(このように時間経過時に発生するイベントをタイマーイベントと言います)。

タイマーイベントの受付は Tk クラスのオブジェクト app を用いて下記のように after メソッドを実行します。

タイマーイベントの受付
timer = app.after(
    1000, # イベントを発生させる時間[ms]
    timer_func # 時間経過時に実行する関数
)

これにより 1000 ms 後に timer_func 関数が実行されるようになります。

ただし、after メソッドでのタイマーイベント受付は1度のみになります。ですので、上記の場合、after メソッド実行の 1000 ms 後に timer_func 関数が1度のみ実行されることになります。

定期的に実行したい場合は、イベント発生時に実行する関数内で after メソッドを実行してやれば良いです。

例えば下記のように timer_func 関数を作成すれば、1000 ms 毎に “1秒経過しました” が表示されるようになります。

定期的にイベントを発生する関数
def timer_func():
    global app
    global timer
    timer = app.after(
        1000, # イベントを発生させる時間
        timer_func # 時間経過時に実行する関数
    )
    print("1秒経過しました")

after メソッドで指定する関数には引数は不要です。

また after メソッドで受け付けたタイマーイベントは、after_cancel メソッドによりキャンセルする事が可能です。

引数には after メソッドの戻り値として得られるハンドルを指定します。

タイマーイベント受付のキャンセル
app.after_cancel(timer)

Tkinter で作成したアプリの例

最後に主に Tkinter のみを使用して作成した簡単なアプリの例を紹介したいと思います。

お絵描きアプリ
# -*- coding:utf-8 -*-
import tkinter

# マウスボタンが押されていているかどうかの判断用
press = False

def mouse_move_func(event):
    global canvas

    # 現在のマウスの位置
    x = event.x
    y = event.y

    # マウスボタンが押されている時だけ円を描画
    if press:
        canvas.create_oval(x - 3, y - 3, x + 3, y + 3, fill = "blue", width=0)


def mouse_click_func(event):
    global press

    # マウスボタンが押された
    press = True

def mouse_release_func(event):
    global press

    # マウスボタンが離された
    press = False

# アプリの作成
app = tkinter.Tk()

# アプリの画面設定
app.geometry(
    "400x400" # アプリ画面のサイズ
)
app.title(
    "サンプルアプリ" # アプリのタイトル
)

# キャンバスの作成
canvas = tkinter.Canvas(
    app, # キャンバスの作成先アプリ
    width = 400, # キャンバスの横サイズ
    height = 400, # キャンバスの縦サイズ
    bg = "white" # キャンバスの色
)

# キャンバスの配置
canvas.pack()

# イベントの受付
app.bind(
    "<Motion>", # 受付けるイベント
    mouse_move_func # そのイベント時に実行する関数
)

app.bind(
    "<ButtonPress>", # 受付けるイベント
    mouse_click_func # そのイベント時に実行する関数
)

app.bind(
    "<ButtonRelease>", # 受付けるイベント
    mouse_release_func # そのイベント時に実行する関数
)

# アプリの待機
app.mainloop()

マウスがクリックされている間だけマウスの位置に小さな円が描画されるようになっています。

ですので、マウスをクリックした状態でマウスを動かすことで画面上にお絵描きする事ができます。速くマウスを動かすと線が途切れてしまいますが、これは PC の処理能力の限界だと思います…。

とりあえず、割と短い&簡単なスクリプトですが、簡単に GUI アプリが作成できている事が確認できると思います!

スポンサーリンク

まとめ

このページでは Python の標準ライブラリ Tkinter を用いて GUI アプリを作成する方法の紹介をしました。

Tkinter を利用すれば、GUI アプリを作成するのに必要な

  • オブジェクトの作成や配置
  • イベントの受付

が簡単に行う事ができます。

キーボードやマウスの入力も簡単に受け付けられるようになるところが特にオススメな点です。このおかげで GUI アプリを簡単に作成する事が可能になります。

是非このページを参考にして Tkinter を利用してみてください!

オススメ参考書

「このページで紹介したtkinter に興味を持った方」「ゲーム開発に興味のある方」「Python プログラミング初心者の方」には冒頭でも紹介したPythonでつくる ゲーム開発 入門講座がオススメです。

この本は Python プログラミングの初心者向け解説から Tkinter を使用したゲーム開発まで学べる参考書です。 当然 Tkinter やゲーム開発について深く学ぶ事ができます。

また初心者の方にとっては、楽しく Python を学べる点がオススメの理由です。ゲーム開発を通して Python プログラミングを学ぶ事ができ、自分の作成したプログラムの動作を実際に目で確認できるので楽しく勉強できま。

楽しいのでプログラミング学習のモチベーション低下も防ぐ事ができます。

とっつきやすさという点で、Python 初心者向け参考書としてはナンバーワンだと思います。ただちょっとゲーム開発に特化しすぎているので Python の知識を幅広く身につけるためにはもう一冊参考書を購入することをお勧めします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です