テキストボックスのフォーカスを切り替え【tkinter】
Python の GUI ライブラリである tkinter では、テキストボックスが入力対象(アクティブになっている)かを『フォーカス』という言葉で表現します。
このフォーカスを自由に切り替える方法を解説します。
本記事は、Python 3.9.7 で動作を確認しています。
Table of Contents
focus_set()関数
フォーカスしたいテキストボックスウィジェットの focus_set() メンバ関数を呼び出すだけです。
import tkinter
# ~
entry1 = tkinter.Entry()
entry2 = tkinter.Entry()
# フォーカス変更
entry2.focus_set()
# ~
機能の説明はこれだけで十分!というかたはもうオッケーです。
以降は、実際に動作するソースコードで解説していきます。
基本編
シンプルなEntryウィジェット
# ライブラリ取り込み
import tkinter
# トップレベルウィジェット作成
root = tkinter.Tk()
root.geometry("320x240")
# テキストボックスウィジェット作成1
entry1 = tkinter.Entry(root)
entry1.pack()
# テキストボックスウィジェット作成2
entry2 = tkinter.Entry(root)
entry2.pack()
# イベントハンドリング
root.mainloop()
ウィンドウを作成して、テキストボックスを2つ配置するだけのシンプルなプログラムです。
Entry が tkinter のテキストボックスクラスです。
tkinter に見慣れないかたも読みやすくなるよう、最小限のプログラムにしています。コピペで動くようにしてあるので、実際に試してみると良いでしょう。
フォーカスの設定
import tkinter
root = tkinter.Tk()
root.geometry("320x240")
entry1 = tkinter.Entry(root)
entry1.pack()
entry2 = tkinter.Entry(root)
entry2.pack()
# フォーカス設定
entry1.focus_set()
root.mainloop()
Entry ウィジェットの focus_set() を呼び出して、ウィンドウが表示されたときに、ひとつ目のテキストボックスがフォーカスされた状態で起動するようにしています。
任意のテキストボックスが入力できる状態で使い始められるので、これだけでも使い勝手が向上しますよね。
応用編
Enter 入力でフォーカスの切り替え
import tkinter
root = tkinter.Tk()
root.geometry("320x240")
entry1 = tkinter.Entry(root)
entry1.pack()
entry2 = tkinter.Entry(root)
entry2.pack()
# キー入力時のコールバック関数を定義
def on_key1(event):
entry2.focus_set()
# コールバック関数のバインド
entry1.bind("<Key-Return>", on_key1)
# 以下、entry2用
def on_key2(event):
entry1.focus_set()
entry2.bind("<Key-Return>", on_key2)
root.mainloop()
今回は、テキストボックスでキーが入力されたタイミングを知る必要があるので、コールバック用の関数を定義して、テキストボックスウィジェットにバインドします。
『<Key–Return>』は『キーボードのエンターキーが押された』という意味で、まさにエンターキーが押されたときに、バインドした関数が呼ばれるようになります。
テキストボックスでエンターキーが押されたときに、それぞれのテキストボックスがフォーカスされるようにしたプログラムです。
上下キー入力でフォーカスの切り替え
import tkinter
root = tkinter.Tk()
root.geometry("320x240")
# 作成するウィジェット数
WIDGET_NUM = 10
# ウィジェットをまとめるリスト
widget_list = []
# キー入力コールバック
def on_key(event):
# キー入力されたウィジェットの要素番号を取得
idx = widget_list.index(event.widget)
# 上下キーで要素番号を変動
if event.keysym == "Up":
idx -= 1
elif event.keysym == "Down":
idx += 1
# 指定要素へフォーカスを切り替え
widget_list[idx % len(widget_list)].focus_set()
# ウィジェット作成、バインド、リスト追加
for i in range(WIDGET_NUM):
entry = tkinter.Entry(root)
entry.pack()
entry.bind("<Key>", on_key)
widget_list.append(entry)
root.mainloop()
上下キーでのフォーカス移動も書いてみました。そういう要望もあるかもしれませんよね。
コールバック関数の引数である event には、キー入力された状況時の様々な情報が格納されています。『keysym』プロパティには『どのキー』が押されたかの情報が入っているので、上下キーでそれぞれ条件分岐しています。
また、複数のウィジェットを扱うケースを想定して、リストで管理する方法で実装しました。プログラムは少し難しくなったかもしれませんが、実用力が高めのコードになってきています。
異種ウィジェットでフォーカスの切り替え
import tkinter
root = tkinter.Tk()
root.geometry("320x240")
# 様々なウィジェットを追加
widget_list = []
widget_list.append(tkinter.Entry(root))
widget_list.append(tkinter.Checkbutton(root, text="chk1"))
widget_list.append(tkinter.Button(root, text="btn1"))
widget_list.append(tkinter.Entry(root))
widget_list.append(tkinter.Checkbutton(root, text="chk2"))
widget_list.append(tkinter.Button(root, text="btn2"))
# キー入力コールバック
def on_key(event):
idx = widget_list.index(event.widget)
widget_list[(idx + 1) % len(widget_list)].focus_set()
# ウィジェット配置とキーバインド
for w in widget_list:
w.pack()
w.bind("<Key-Return>", on_key)
root.mainloop()
フォーカスの切り替えはテキストボックスに限った機能ではなく、チェックボックスやボタンでもフォーカス切り替えができます。Windows の標準操作である Tab キーで入力したときと同じように振る舞います。
チェックボックスやボタンは Space キーでトリガーが発動するので、フォーカスの切り替えと干渉せずに動作します。
GUI をどう使ってもらいたいか、実装次第で自由にコントロールできますね!
tkinter の技術書籍
残念ながら、tkinter はまともな日本語の書籍がありません。(2021年9月時点)
上記は Python 3.9 に対応した優良書籍(英語)です。
Qiita などで見かける tkinter のプログラムは、正直書き方が古かったり誤用が多い記事ばかりです。まさにその古いプログラムを払拭してくれる書籍になっています。
Python エンジニアなら手元にあってよいでしょう。
今回は、ウィジェットのフォーカス切り替えを重点においた内容にしてみました。
入力項目がアッチやコッチと飛ばされるツールをたまに見かけます。機能が優れていても、使い勝手が悪いツールって敬遠されがちですよね。
開発者なら、誰でも便利と感じてくれる GUI のツールを作りたいはずなので、参考になってくれたら幸いです。
以上、『テキストボックスのフォーカスを切り替え【tkinter】』でした。