Tkinterの使い方:Tk クラスでメインウィンドウを作成

メインウィンドウ作成解説ページのアイキャッチ

このページは Tkinter を使ってメインウィンドウを作成・操作する方法について解説したいと思います。

メインウィンドウの作成

メインウィンドウは下記を実行することで生成することができます。

  • Tkinter の Tk クラスのインスタンスを生成する

メインウィンドウを生成するスクリプト例は下記のようになります。

メインウィンドウの作成
import tkinter
app = tkinter.Tk()
app.mainloop()

実行すると下の図のようなメインウィンドウが表示されることが確認できると思います(見た目は OS 等により異なります)。

メインウインドウの表示

Tkinter のインポート

下記では Tkinter モジュールを利用するために tkinter のインポートを行っています。Python3 では全て小文字で「tkinter」と記述することに注意しましょう。

tkinter のインポート
import tkinter

メインウィンドウの作成(Tk()

メインウィンドウを実際に作成しているのは下記になります。tkinter.Tk クラスのインスタンスを生成しており、これによりメインウィンドウが作成されます。

メインウィンドウの作成
app = tkinter.Tk()

tkinter では、まずメインウィンドウを作成し、このメインウィンドウ内にウィジェットを作成・配置していくことで GUI アプリを開発を行していくのが基本的な流れになります。

メインループ(mainloop)

ではスクリプトの最後の mainloop では何を行っているでしょうか?この mainloop は tkinter での GUI アプリ開発において非常に重要なメソッドになっていますので、少し詳しく説明しておきます。

メインループ
app.mainloop()

ここで実行している mainloop は簡単にいうと下記の2つを行っています。

  • アプリの待機
  • イベント処理

アプリの待機

プログラムは最後まで実行されると、自動的に終了してしまいます。例えば下記のようなスクリプトを実行しても GUI アプリが即座に終了してしまうことになります。

メインループなし
import tkinter
app = tkinter.Tk()

通常 GUI アプリではユーザーからの操作(ボタン操作やマウス操作など)を受け付けるために、待機させておくことが必要です。

例えば計算機アプリは、起動すると待機し、その後ユーザーからのマウス操作やキーボード操作の受け付けを待ちますよね。こんな感じで自作したアプリも待機してユーザーからの操作を待つことが必要です。

アプリが待機している様子

一方で mainloop の中では無限ループが実行されますので、mainloop さえ実行しておけば GUI アプリが終了することはありません(終了ボタンが押されるなど、意図的に終了した場合に GUI アプリは終了します)。

また、これにより GUI アプリを待機させ、ユーザーからの操作を受け付けることが可能になります。

ちなみに mainloop は前述の通り無限ループを行っていますので、mainloop の後ろ側にスクリプトを記述してもすぐには実行されません。GUI アプリ終了時(終了ボタンが押された時など)に実行されることになります。

mainloopの後ろ側の処理
import tkinter
app = tkinter.Tk()
app.mainloop()
print("このメッセージはアプリ終了するまで表示されません")

ですので、下記のようなことを mainloop 実行後に行っても、GUI アプリ終了までは処理されませんので注意しましょう。

  • bind メソッドによるイベントの受付
  • ウィジェットの生成や配置

イベント処理

さらに、マウスクリックやボタンクリック等のイベント発生時に、そのイベントに対する処理(bind メソッド等で設定された処理)を呼び出す処理も、この mainloop 内で行われます。

例えば計算機アプリでは、ユーザーからマウス操作やキーボード操作のイベントを受け付けて指定された数字を表示したり計算を実行したりできますよね。このイベントを受け付け&受け付けたイベントに応じた処理の実行は mainloop 内で行われます。

アプリが待機している様子

mainloop が実行されないと、Tkinter を利用して設定したイベント処理を行うことはできません

また、メインウィンドウやウィジェットは作成(や配置)をしてもすぐには画面には表示されず、これらの画面表示mainloop 内で行われます。

メインウインドウやウィジェットの設定変更(例えばサイズ変更)時も mainloop 内での処理により画面に反映されます(ただし後述する update メソッドを利用すれば mainloop 外からでも画面表示や画面への反映を行うことも可能です)。

ですので、 Tk クラスのインスタンスを生成したとしても、基本的には mainloop が実行されるまで画面には表示されません。

例えば下記のように sleep を入れると mainloop が実行されるまで表示されないことが実感しやすいと思います。

メインウィンドウが表示されるタイミング
import tkinter
app = tkinter.Tk()

# sleep
import time
time.sleep(5)

app.mainloop()

ここまで解説してきたように、mainloop は Tkinter を利用した GUI アプリ開発では非常に重要です。mainloop を行うことを必ず忘れないようにしましょう!

メインウィンドウへの操作

次はメインウィンドウに対する操作(Tk クラスのメソッド)にどのようなものがあるかを説明していきたいと思います。

まず Tk クラスの全メソッドは下記により表示することができます。

Tk クラスのヘルプ
import tkinter
help(tkinter.Tk)

ここではこの中から、特にメインウィンドウに対する操作として私がよく使うメソッドを紹介します。

mainloop

mainloop メソッドはメインウインドウの作成方法で解説したように、メインループによりアプリを待機させるメソッドです。

このメインループの中で受け付けたイベントの処理を実行したり、ウィジェット等の画面への表示が行われます。この mainloop メソッドは必ず実行するようにしましょう。

geometry

geometry はメインウィンドウ表示時の「サイズと位置」を指定するメソッドになります。

geometryの定義
geometry(self, newGeometry=None)

引数には下記の形式の文字列を指定します。

geometryの引数
geometry("WIDTHxHEIGHT+X+Y")

これにより “WIDTH x HEIGHT” サイズのメインウィンドウが、ディスプレイの “(X, Y)” 座標に表示されます。

太文字&赤背景で示した箇所には、実際には設定値を半角数字で指定します(単位はピクセル)。

例えば “600 x 300” サイズのメインウィンドウをディスプレイの “(400, 100)” 座標に表示するためには下記のように geometry メソッドを実行します。

geometryの実行例
import tkinter
app = tkinter.Tk()
app.geometry("600x300+400+100")
app.mainloop()

実行すれば、下の図のように指定したサイズのメインウィンドウが指定した座標に表示されます(おそらくサイズや位置はタイトルバーを考慮せずに設定されます)。

geometryの実行結果

また、「位置」を省略し「サイズ」のみを指定する形式でも OK です。

geometryの引数
geometry("WIDTHxHEIGHT")

title

titleはメインウィンドウのタイトルを指定するメソッドになります。

titleの定義
title(self, string=None)

title メソッドにはタイトルとして表示したい文字列を指定します。

titleの実行例
import tkinter
app = tkinter.Tk()
app.title("私が開発中のアプリ")
app.mainloop()

実行すればタイトルバーに指定した文字列が表示されるようになります。

titleの実行結果

minsize

minsize はメインウィンドウの「最小サイズ」を設定するメソッドになります。

minsizeの定義
minsize(self, width=None, height=None)

ユーザーがメインウィンドウを小さくしすぎた際に、アプリのレイアウトが崩れることを防ぐのに有効です。

第1引数に設定したいウィンドウの最小の幅、第2引数に設定したいウィンドウの最小の高さを指定します。

minsizeの実行例
import tkinter
app = tkinter.Tk()
app.minsize(500, 100)
app.mainloop()

上記スクリプトを実行し、ウィンドウのサイズを変更してみると、指定したサイズよりも小さくできないことが確認できると思います。

minsizeの実行結果

maxsize

maxsize はメインウィンドウの「最大サイズ」を設定するメソッドになります。

maxsizeの定義
maxsize(self, width=None, height=None)

第1引数に設定したいウィンドウの最大の幅、第2引数に設定したいウィンドウの最大の高さを指定します。

maxsizeの実行例
import tkinter
app = tkinter.Tk()
app.maxsize(500, 100)
app.mainloop()

上記スクリプトを実行し、ウィンドウのサイズを変更してみると、指定したサイズよりも大きくできないことが確認できると思います。

maxsizeの実行結果

resizable

resizable はメインウィンドウの「サイズ変更の有効 / 無効」を設定するメソッドになります。

resizableの定義
resizable(self, width=None, height=None)

第1引数はウィンドウの幅のサイズ変更の有効(True) / 無効(False)、第2引数はウィンドウの高さのサイズ変更の有効(True) / 無効(False)を指定します。

resizableの実行例
import tkinter
app = tkinter.Tk()
app.resizable(False, False)
app.mainloop()

上記スクリプトを実行し、ウィンドウのサイズを変更し用としてみてもサイズが変更できないことが確認できると思います。

メモ

resizable は、仕様上は幅と高さそれぞれに対してサイズの変更の有効 / 無効を設定できるようになっているはずですが、どうも私が試した限りでは「一方でも True だと両方有効になる」という振る舞いになってしまいました…。

Tkinter のバージョンにもよるのかもしれませんが、同じ現象が起きるかもしれませんので注意してください。

ちなみに minsizemaxsize をうまく利用することにより、ウィンドウのサイズ変更の有効 / 無効を設定することも可能です。

例えば下記のように minsizemaxsize の第1引数に同じ値を指定すれば、幅のサイズ変更は無効になり、高さのみサイズ変更が可能になります。

minsizeとmaxsizeによるサイズ変更の制限
import tkinter
app = tkinter.Tk()
app.minsize(500, 100)
app.maxsize(500, 600)
app.mainloop()

destroy

destroy はメインウィンドウ上のウィジェットを全て破棄して直ちにアプリを終了するメソッドになります。

destroyの定義
destroy(self)

引数は不要です。

アプリの終了ボタン(Mac だとアプリ画面左上の赤丸、Windows だとアプリ画面右上の×ボタン)がクリックされた時にもこの destroy メソッドが実行されます。

直ちにアプリを終了させたい場合に destroy メソッドは有効です。

使用例は次の protocol で合わせて紹介します。

protocol

protocol はメインウィンドウに対するイベントを受付の処理を設定するメソッドの1つになります。

例えば終了ボタンでウィンドウが閉じられる場合は、WM_DELETE_WINDOW という名前のイベントが発生します。

通常はこのイベントが発生すると、destroy メソッドが実行されてアプリが終了しますが、protocol メソッドを利用すると、その処理を横取りして他の処理に置き換えることができます。

protocolの定義
protocol(self, name=None, func=None)

第1引数にはイベント名、第2引数にはそのイベント発生時に実行する関数名を設定します。

protocolの使用例
import tkinter

def no_destroy():
	print("終了しません")

app = tkinter.Tk()
app.protocol("WM_DELETE_WINDOW", no_destroy)
app.mainloop()

上記のスクリプトを実行すると、アプリの終了ボタンを押してもアプリが終了しなくなります(強制終了の仕方がわからない方は実行しない方が良いです…)。

これは、WM_DELETE_WINDOW イベント(終了ボタンでウィンドウが閉じられる際に発生するイベント)発生時に実行する関数が destroy ではなく no_destroy に置き換わったためです。

例えば下記のようにメッセージボックスを使用すれば、終了ボタンがクリックされた際にメッセージボックスを表示し、「OK」ボタンが押された場合のみ destroy が実行するようにもできます。

protocolとdestroyの使用例
import tkinter
from tkinter import messagebox

def ask_destroy():
	global app

	ret = messagebox.askokcancel(
		"終了の確認",
		"本当に終了しますか?"
	)
	
	if ret:
		app.destroy()

app = tkinter.Tk()
app.protocol("WM_DELETE_WINDOW", ask_destroy)
app.mainloop()

実行結果は下のアニメーションのような感じになります。

protocolの使用例

イベントに関しては他にも様々なメソッドが用意されています。

このイベントに関しては別ページを用意して解説していきたいと思います。

update

update は実行時点でメインウィンドウを現状の設定で画面に表示するメソッドになります。

前述の通り、基本的にはメインウィンドウやその他のウィジェットは mainloop での処理時に画面に表示されたり設定の変更が反映されたりします。

しかし、この update を実行すれば、mainloop に入る前に直ちに画面への表示が設定変更の反映を行うことができます。

updateの定義
update(self)

引数は不要です。

config

config はメインウィンドウに対して各種設定を行うメソッドになります。configure も同じく config 同様のメソッドになります。

configの定義
config(self, cnf=None, **kw)

設定したいキーワードを用いて「キーワード=設定値」の形式(キーワード引数)で指定します。

どんなキーワードが使用できるかは keys メソッドを実行することで確認することが可能です。

キーワード一覧の表示
import tkinter
app = tkinter.Tk()
print(app.keys())

実行すると下記のようにキーワード一覧が表示されます。例えば、’bg‘ はメインウィンドウの背景色、 ‘cursor‘ はカーソルの形式を指定するためのキーワードになります。

['bd', 'borderwidth', 'class', 'menu', 'relief', 'screen', 'use', 'background', 'bg', 'colormap', 'container', 'cursor', 'height', 'highlightbackground', 'highlightcolor', 'highlightthickness', 'padx', 'pady', 'takefocus', 'visual', 'width']

同じ感じで、config メソッドを「引数なし」で実行すれば、各キーワードに対する現在の設定値を取得することもできます。

下記はマウスカーソルをハートに、メインウィンドウの背景を赤色に設定するスクリプトになります。

configの使用例
import tkinter

app = tkinter.Tk()
app.config(
	cursor="heart", 
	bg="red",
)
app.mainloop()

実行すると下の図のようなメインウィンドウが表示されます(カーソルはキャプチャできなかったで表示されていません….)。

configの使用例

この config メソッドは全ウィジェットで使用できるので、使い方や使用できるキーワードの調べ方は覚えておきましょう!

スポンサーリンク

まとめ

このページでは、Tkinter でメインウィンドウを作成する方法について解説しました。

メインウィンドウは Tk クラスのインスタンスを生成するだけで作成することができます。

この作成したメインウィンドウは Tk クラスのメソッドを利用して様々な操作・設定を行うことも可能です。

特に mainloop は Tkinter のアプリ開発では非常に重要ですので、忘れず実行するようしましょう!

オススメ参考書

Tkinter に興味がある方には下記のPythonでつくる ゲーム開発 入門講座がオススメです。

Tkinter をゲーム開発を通して「楽しく学ぶ」ことができます。Python 入門者、Tkinter 入門者の方にオススメです。

コメントを残す

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