序章 Python の学習を始めたばかりで、簡単なアプリケーションを 1 つまたは 2 つ作成したことがあるかもしれません。おめでとう!しかし、今何ですか?では、ピカピカの新しい Python アプリと対話するためのグラフィカル ユーザー インターフェイス ("GUI") を構築するのはどうでしょうか? Python で GUI アプリケーションを構築するには、 や など、いくつかのオプションがあります。ただし、このガイドでは について紹介します。 PyQt wxPython Tkinter 「Tk インターフェイス」の略である は、GUI を構築するための Python の標準であり、 に含まれています。これは、さまざまなプログラミング言語でグラフィカル インターフェイスを構築するために使用できる GUI の無料のオープン ソース ライブラリである へのバインディングです。 Tkinter Python 標準ライブラリ ウィジェット Tk GUI ツールキット このチュートリアルでは、ユーザーが選択したタイムゾーンで現地時間を表示する基本的な GUI アプリケーションの設計について説明します。この手順では、アプリケーションを段階的に構築し、GUI 要素のレイアウト、ユーザー入力のキャプチャ、GUI 要素のコールバック メソッドへのバインドなど、 を操作する際の重要な概念のいくつかについて説明します。 Tkinter 前提条件 このガイドを完了するには、次のものが必要です。 ました。 Python をインストールし インストールされた 。 pip タイムゾーン ライブラリをインストールしました。ライブラリは を使用してインストールできます。 pytz pip pip install pytz このガイドでは、 と という用語を同じ意味で使用します。 ルート ウィンドウ メイン ウィンドウ ステップ 1 - 新しい Python アプリケーションを作成し、必要なインポートを設定する という名前の新しい Python アプリケーションを作成し、次の ステートメントを追加して 、 、および モジュールをインポートします。 timezone.py import Tkinter datetime pytz import tkinter as tk import datetime import pytz ステップ 2 - タイムゾーンを追加する このガイドには、 でサポートされているタイムゾーンのごく一部である米国のタイムゾーンのセットが組み込まれています。アプリケーションの機能は、追加の タイムゾーン名を追加することで拡張できます。次のコマンドを実行すると、 で使用できるタイムゾーンの完全なリストを出力できます。 pytz pytz pytz print(pytz.all_timezones) を介して利用可能な米国のタイムゾーンのセットは、リストとして指定されます。 pytz import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] ステップ 3 - Tk クラスのインスタンスを作成する クラスをインスタンス化すると、タイムゾーン アプリケーションの GUI のメイン ウィンドウとして機能する が作成されます。 Tk ルート ウィンドウ import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() ステップ 4 - メイン ウィンドウのセットアップ この手順では、ルート ウィンドウ、特にそのタイトル、ジオメトリ、およびサイズ変更可能性を構成します。 ステップ 4a - メイン ウィンドウのタイトルを設定する ウィンドウのタイトルは メソッドを使用して設定されます。 title import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") ステップ 4b - メイン ウィンドウの幅と高さの設定 ウィンドウの幅と高さの値 (ピクセル単位) を変数に割り当てて、コードを理解しやすくすることができます。 import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 ステップ 4c - メイン ウィンドウの中心位置の計算 メイン ウィンドウは画面のどこにでも配置できます。たとえば、中央、左上隅などです。中央に配置されたウィンドウは見栄えがよく、ルート ウィンドウの を使用してメイン ウィンドウの中央位置を決定できます。 および メソッドといくつかの簡単な計算。これら 2 つのメソッドは、メイン ウィンドウを中央に配置するための適切な (x,y) 座標を計算するために使用される画面の幅と高さを返します。ウィンドウの幅と高さと同様に、中心位置の値も変数に割り当てて、コードを読みやすくすることができます。 winfo_screenwidth() winfo_screenwidth() winfo_screenheight() import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) と の値もピクセルで表され、両方の計算値が整数になるように が使用されることに注意してください。 center_x center_y int ステップ 4d - メイン ウィンドウのジオメトリの設定 メイン ウィンドウのサイズと位置を指定する ウィンドウ ジオメトリは、ルート ウィンドウの メソッドを使用して設定されます。簡単にするために、実行時にジオメトリ変数の式を補間する、書式設定された文字列リテラルまたは を使用できます。次のコード ブロックに従って、 リテラルは メソッドにパラメーターとして渡されます。 root geometry f-string f-string geometry import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") ステップ 4e - メイン ウィンドウのサイズ変更可能性の設定 x 軸と y 軸に沿ったルート ウィンドウのサイズ変更可能性は、ルート ウィンドウの なメソッドを介して設定できます。 なメソッドは、 と のパラメーターをこの順序で受け入れます。いずれかのパラメーターの またはゼロ以外の値は、メイン ウィンドウが関連付けられた軸に沿ってサイズ変更可能であることを指定します。いずれかのパラメーターの または の値は、メイン ウィンドウが指定された軸に沿ってサイズ変更できないことを指定します。タイマー アプリケーションは、高さと幅の両方に の値を使用して、メイン ウィンドウのサイズが変更されないようにします。 resizable resizable height width True False 0 False import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) ステップ 5 - ウィジェット レイアウトのグリッドを指定する は、 を使用してさまざまな方法でメイン ウィンドウの上に配置できます。通常、ウィジェットは次の 3 つの方法で配置できます。 ウィジェット ジオメトリ マネージャー メソッドを使用して ます。 ジオメトリ マネージャーは、ルート ウィンドウまたは親ウィジェットに追加される前に、ウィジェットをブロックに編成します。 について考える不完全だがおそらく役立つ方法は、食料品を買い物袋に追加することを考えることです。アイテムは、必ずしもバッグ内の事前定義された場所に追加されるとは限りません。むしろ、すべてのアイテムがバッグに入れられるまで、使用可能なスペースを使用して、次々と されます。 ジオメトリ マネージャも同様に機能します。 pack() パックされ pack() パッキング 梱包 pack() メソッドを使用して されます。 ジオメトリ マネージャーは、ウィジェットをルート ウィンドウまたは親ウィジェットの特定の事前定義された位置に します。このジオメトリ マネージャーは、正確な GUI レイアウトを構築するときに明らかに役立ちます。 place() 配置 place() 配置 メソッドを使用して として配置します。グリッドは、2 次元の行/列テーブルです。ウィジェットを配置する特定の行と列を指定して、ウィジェットをグリッドに追加します。グリッドは、ルート ウィンドウの および メソッドを使用してセットアップされます。これらの各メソッドには、 と の属性があります。 属性は、開始基準 を使用して列または行の位置を指定します。 属性は、他の列に対する特定の列または行のサイズを指定します。たとえば、 の重みが で、 の重みが の場合、 は の 3 倍の大きさになります。 grid() グリッド columnconfigure rowconfigure index weight index 0 weight 列 0 1 列 1 3 列 1 列 0 グリッドは要素を隣り合わせに配置する場合に便利で、実装も比較的簡単です。タイムゾーン アプリケーションは、4 つの等しい列に分割されたメイン ウィンドウ グリッドを使用します。 import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) ステップ 6 - ウィジェットを追加する このステップでは、ステップ 4 で定義したメイン ウィンドウ グリッドにウィジェットを追加します。タイムゾーン アプリケーションは 3 つの ウィジェットを使用します。 TKinter Label Listbox Button Tkinter の ウィジェットと ウィジェットは、その名前の通りです。 ウィジェットを使用すると、プログラマはテキスト (つまり、ラベル) を表示できます ウィジェットは、ボタンを表示するために使用されます。 ウィジェットは、オプションのリストから値を選択するために使用されます。 Label Button Label Button Listbox もちろん、 、 、 ウィジェットなど、上記の 3 つ以外のウィジェットもあります。正式な は、Tk ツールキットで利用できるウィジェットについて詳しく知るのに役立つリソースです。 SpinBox Entry Message Tk コマンドのドキュメント ステップ 6a - ウィジェットを作成する 各ウィジェット クラスのインスタンスは、GUI デザインで使用される特定のウィジェットに対して作成されます。タイムゾーン アプリケーションは、2 つの ウィジェット、1 つの ウィジェット、および 1 つの ウィジェットの 4 つのウィジェット インスタンスを使用します。 Label Listbox Button import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") 上記のコード ブロックに見られるように、各ウィジェット インスタンスは ウィンドウに「接続」されています。 ウィジェットには、特別な Tkinter クラスのインスタンス化も必要です。これは、ユーザーが の 属性を介して選択できるタイムゾーン オプションのリストをウィジェットに提供するために使用されます。各 ウィジェットによって表示されるテキストは、 属性を使用して構成できます。 のテキスト値は、ユーザーが選択したタイムゾーンの時間を「取得」するたびに動的に設定されるため、空白のままにします。 root Listbox Variable() Listbox listvariable Label text time_label ステップ 6b - ウィジェットをグリッドに配置する ステップ 5a で作成されたウィジェット インスタンスは、 メソッドを使用して、ステップ 4 で定義されたグリッドに配置できます。タイムゾーン アプリケーションは、次の メソッド属性を使用してレイアウトを定義します。 grid() grid() : 基準を使用してウィジェットが配置される特定の列を指定します。 column 0 : ベースを使用してウィジェットが配置される特定の行を指定します。 row 0 : ウィジェットが指定された数の列にまたがるように指定します。たとえば、値が のウィジェットは、ウィジェット自体が 3 列より小さい場合でも、3 列にまたがります。 columnspan columnspan=3 : Tkinter のデフォルトの動作は、セルの水平方向および垂直方向の中央 (つまり、特定の行/列の位置) にウィジェットを配置することです。このデフォルトの動作は、コンパスのような値 ( 、 、 、 、 、 、 、 など) を使用する 属性を使用してオーバーライドでき、ウィジェットのセル の特定の位置にウィジェットを配置できます。たとえば、 は、ウィジェットをグリッド セルの西隅に配置するように指定します。同様に、 は、ウィジェットをグリッド セルの東隅に配置する必要があることを指定します。 sticky NW N NE W E SW S SE sticky 内 sticky=tK.W sticky=tK.E 、 : および 属性は、ピクセルで指定された値でそれぞれ x 軸および y 軸のパディングを追加するために使用されます。当然のことながら、パディングは、ウィジェットがルート ウィンドウや他のウィジェットの端に直接「ぶつかる」ことがないように、よりプロフェッショナルな外観の GUI を提供できます。 padx pady padx pady import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10) ステップ 7 - Get Time ボタンのコールバック メソッドを作成する 手順 5 で作成した ボタンをユーザーがクリックしたときにイベントを処理するには、コールバック メソッドを定義する必要があります。 select_timezone_button ステップ 7a - Get Time ボタンのバインド コールバック ロジックを定義する前に、最終的にコールバック コードを含むメソッド名にボタンをバインドすることをお勧めします。 メソッドを 関数と組み合わせて使用して、 を指定されたコールバック メソッドにバインドできます。また、 関数を使用して および ウィジェットへの参照をコールバック パラメータとして渡すことにも注意してください。 と はグローバル スコープ内にあるため、これらのコールバック パラメータは実際には必要 。ただし、引数をコールバック関数に渡す方法を示すことは間違いなく役に立ちます。 bind() lambda select_timezone_button lambda select_timezone_listbox time_label select_timezone_listbox time_label ありません import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_button.bind("<Button>", lambda e, args=[select_timezone_listbox, time_label]: get_timezone_time(e, args)) ステップ 7b - コールバック ロジックの定義 ボタン クリック イベントを処理するためのコールバック ロジックを以下に定義します。 def get_timezone_time(e, args): select_timezone_listbox = args[0] time_label = args[1] selection_index = select_timezone_listbox.curselection() selected_timezone = select_timezone_listbox.get(selection_index) now_time = datetime.datetime.now() tz_time = now_time.astimezone(pytz.timezone(selected_timezone)) tz_formatted = tz_time.strftime("%H:%M:%S") time_label.configure({"text": f"The time in {selected_timezone} is {tz_formatted}."}) time_label.update() および メソッドは、ユーザーが選択したタイムゾーンを ウィジェットへの参照から取得するために使用されます。次に、ユーザーの現在の時刻が、選択したタイムゾーンの時刻に変換されます。最後に、 メソッドを使用して、 への参照の 属性を、選択したタイムゾーンの現地時間に変更します。 メソッドは、 ウィジェットを新しいテキスト値で更新するよう「強制」するために使用されることに注意してください。 curselection() get() select_timezone_listbox configure time_label text update() time_label ステップ 8 - アプリケーションを完成させて実行する ルート ウィンドウの メソッドは、コードの最後の行として適用されます。 メソッドは、ユーザーが終了するまで GUI を無限ループで実行します。 mainloop() mainloop() 完成したコードは次のとおりです。 import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] def get_timezone_time(e, args): select_timezone_listbox = args[0] time_label = args[1] selection_index = select_timezone_listbox.curselection() selected_timezone = select_timezone_listbox.get(selection_index) now_time = datetime.datetime.now() tz_time = now_time.astimezone(pytz.timezone(selected_timezone)) tz_formatted = tz_time.strftime("%H:%M:%S") time_label.configure({"text": f"The time in {selected_timezone} is {tz_formatted}."}) time_label.update() root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10) # Bind button to callback. select_timezone_button.bind("<Button>", lambda e, args=[select_timezone_listbox, time_label]: get_timezone_time(e, args)) root.mainloop() アプリケーションを起動すると、GUI は次のようになります。 アプリケーションを使用するには、リスト ボックスをクリックし、キーボードの上下カーソル キーを使用してタイムゾーン オプションをスクロールします。 [ ] ボタンをクリックして、選択したタイムゾーンで現在の時刻を表示します。 時刻を取得 次のステップ を使用した最初の Python GUI アプリケーションの作成、おめでとうございます!はじめにで述べたように、このガイドはいくつかの基本的な概念を紹介するように設計されています。前述の と リファレンスは、より高度な Tkinter の特徴と機能について学習するのに役立つ 2 つの優れたリソースです。 Tkinter Python 標準ライブラリ ドキュメント Tk コマンド ドキュメント Tkinter GUI アプリケーションは、非ネイティブなルック アンド フィールを持っていると批判されることがあります。それは本当かもしれません。しかし、ツールキット ウィジェットは高度に構成可能であり、Tkinter GUI アプリケーションは、外部の Python パッケージをインストールする必要なく比較的迅速に構築できます。 正式なドキュメント以外にも、Tkinter を使用してより洗練された GUI アプリケーションを構築する方法を学ぶための無数のチュートリアルがインターネット経由で入手できます。