Tkinterの使い方:validation機能の使い方(エントリーウィジェットの拡張)

validationの解説ページアイキャッチ

このページでは、tkinter のエントリーウィジェットで利用可能な validation 機能について解説していきます。

エントリーウィジェット自体については下記ページで解説していますので、エントリーウィジェットについて知りたい方は下記ページを読んでみていただけると幸いです。

エントリーウィジェットの説明ページアイキャッチTkinterの使い方:エントリー(Entry)の使い方

validation とは

validation とは「検証」とか「妥当性確認」という意味を持つ単語になります。

tkinter のエントリーウィジェットには、ユーザーが入力した文字列に対する validation 機能(つまりユーザーが入力した文字列の “妥当性を確認する” 機能)を持たせることができます。

要は、ユーザーがエントリーウィジェットに実際に入力した文字列が妥当であるかどうかの確認を行うようにすることができます。

さらに、”妥当でない” と判断した際には、その文字列の入力を拒否するようなことができます。

つまり、”プログラマーが期待する文字列のみ” をユーザーが入力可能なエントリーウィジェットを作成することができます。

例えば生年月日を西暦で入力するエントリーウィジェットを用意した時、ユーザーには “半角数字のみ” を入力してもらいたいはずです。

でも、ユーザーがその半角数字を入力してくれるとは限らないですよね…。

エントリーウィジェットも単に作成しただけだとどんな文字列の入力も受け付けてしまいます。

こんな時に便利なのが validation 機能です。validation 機能を利用すれば、”半角数字のみ” など、入力できる文字列を制限するエントリーウィジェットを簡単に実現することができます。

validation 機能の使い方

では、続いてこの validation 機能をどうやって利用するかについて解説していきます。

エントリーウィジェットに validation 機能を設定するためには、下記の手順を踏む必要があります。

  1. validation を行う関数を作成する
  2. 1. で作成した関数を基に Tcl 関数を作成する
  3. エントリーウィジェットを作成する
    • この時に下記のオプション指定を行う 
      • validatevalidation を行うタイミングを指定
      • vcmd:2. で作成した Tcl 関数の関数名と 1. で作成した関数で受け取る引数を指定

実際に validation 機能を設定したエントリーウィジェットを作成するスクリプト例は下記のようになります。

validationを設定したエントリーウィジェット
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(diff):

	if not diff.encode('utf-8').isdigit():
		# 妥当でない(半角数字でない)場合はFalseを返却
		return False

	# 妥当(半角数字である)の場合はTrueを返却
	return True

app = tkinter.Tk()

# 2. 1.で作成した関数を基にしたTcl関数を作成する
tcl_isOk = app.register(isOk)

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key', # validationを行うタイミング
	vcmd=(tcl_isOk, '%S') # validationを行うTcl関数とその関数の引数
)
entry.pack()

app.mainloop()

このスクリプトを実行して作成されるエントリーウィジェットは “半角数字のみ” が入力可能になります。それ以外の文字は入力できないはずです。

これは、このスクリプトを実行することで起動するアプリが次のような動作をするためです。

  • エントリーウィジェットに文字を入力される
  • 入力した文字が isOk 関数の引数 diff に渡される
  • isOk 関数で diff が半角数字以外の場合は False を返却する(半角数字の場合は True を返却する)
    • False が返却された場合はエントリーウィジェットへの文字の入力が拒否される
    • True が返却された場合はエントリーウィジェットへの文字の入力が反映される

要は、エントリーウィジェットの文字が変更されたタイミング(validate オプションに指定したタイミング)で validation を行う isOk 関数(vcmd オプションで指定した Tcl 関数の元になる関数)が実行されるようになり、この関数が False を返却した場合は、validation を行う原因となった文字の変更が拒否されます。

このエントリーウィジェットでは “半角数字のみ” 入力可能ですが、このように動作するのは 1. で作成する関数 isOK が引数で受け取った文字が半角数字の場合のみ True を返却するようになっているためです。1. で作成する関数を変更すれば、他の種類の文字のみを入力可能なように設定することも可能です。

また、文字が変更されたタイミングで validation が行われるのは(つまり isOK 関数が実行されるのは)、3. で指定する validate オプションに 'key' を指定しているためです。validate オプションへの指定を変更すれば、他のタイミングで validation を行うことも可能です。

さらに、validation を行う isOK 関数の引数には変更のあった部分の文字のみが渡されます。これは 3. で指定する vcmd オプションに (tcl_isOk, '%S') を指定しているためです。vcmd オプションへの指定を変更すれば、もっと他のデータを引数として受け取れるようになります。

ではこれらに具体的にどのような指定をすれば、どのように validation 機能が動作するのか?この点も含めて、validation を行うために必要な下記の3つの手順の詳細を説明していきたいと思います。

  1. validation を行う関数を作成する
  2. 1. で作成した関数を基に Tcl 関数を作成する
  3. エントリーウィジェットを作成する

説明の都合上、3. → 1. → 2. の順番で説明していきます。

スポンサーリンク

エントリーウィジェット作成する

エントリーウィジェットに validation 機能を設定するためには、エントリーウィジェットの作成時、つまり Entry クラスのコンストラクタ実行時に、下記のオプションを指定するようにします。

  • validatevalidation を行うタイミングを指定
  • vcmd:2. で作成した Tcl 関数の関数名と 1. で作成した関数で受け取る引数を指定

上記のようにオプションを指定することで、エントリーウィジェットに対して validate で指定した操作が行われたタイミングで  1 . で作成した関数が実行されるようになります。

以降では各オプションの詳細を解説していきます。

validate オプション

validate オプションでは、validation を行うタイミング(つまり、1. で作成したコールバック関数を実行するタイミング)を指定します。

validate オプションに指定可能なパラメータは下記の6つになります。

  • 'focusin':エントリーウィジェットにフォーカスがあてられた時
  • 'focusout':エントリーウィジェットからフォーカスが外れた時
  • 'focus':上記2つのどちらかが発生した時
  • 'key':エントリーウィジェットの文字列に変化があった時
    • ユーザーがからの文字列の挿入・削除が行われた時
      • キーボード操作だけでなくペースト操作などでも
    • ウィジェット変数の get メソッドで文字列が変更された時
  • 'all':上記4つのどれかが発生した時
  • 'none':どのタイミングでも validation を行わない

文字の入力自体を制限したい(例えば半角数字だけを入力可能にしたいなど)のであれば 'key' を指定し、エントリーの文字が変化するたびに validation するのが良いと思います。

vcmd オプション

vcmd オプションでは、validation を行う関数と、その関数に渡される引数の設定を行います。

validatecommand オプションでも同様の設定を行うことが可能です。

vcmd オプションには下記の要素を持つタプルを指定します。

  • 0 要素:validation を行う関数を基に作成した Tcl 関数の名前
  • 1 要素以降:validation を行う関数に渡す引数の種類

まず第 0 要素には、自身で作成した validation を行う関数ではなく、その関数を基に作成した Tcl 関数の名前を指定する必要があります。Tcl 関数の作成方法やその名前の取得方法は後述のTcl 関数を作成するで解説します。

また、第 1 要素以降には validation を行う関数に渡す引数の種類を '%x' の形式で指定します。x 部分にはアルファベットを指定し、このアルファベットに応じて validation を行う関数に渡す引数の種類が変わります。また、'%x',(カンマ)区切りで複数指定することができます。

1 要素以降に指定可能な '%x' と、それに応じて validation を行う関数に渡される引数の詳細は下記のようになります('%d''%i' を指定した場合でも数値ではなく文字列が引数として渡される点に注意してください)。

  • '%d'validation を行う引き金になったアクションを表す文字列
    • '0':ユーザーによってエントリーウィジェットの文字列が削除された
    • '1':ユーザーによってエントリーウィジェットに文字列が挿入された
    • '-1':上記以外(フォーカスがあてられた、フォーカスが外れた等)
  • '%i':何文字目からの文字に対して削除や挿入が行われたかを表す文字列
    • 削除や挿入以外を引き金に validation が行われている場合は -1 になる
  • '%P':削除や挿入後の文字列
    • フォーカス関連で validation が行われた場合は、現在のエントリーウィジェットの文字列が引数として渡される
      • この場合は '%s' の値と同じになる
  • '%s':削除や挿入前の文字列
  • '%S':削除された文字列 or 挿入された文字列
    • フォーカス関連で validation が行われた場合は空文字
  • '%v'validate オプションに指定されている値を表す文字列
  • '%V'validation が行われている理由
    • 基本は validate オプションに指定する値が設定されている('focusin''focusout''key' など)
    • ウィジェット変数の set メソッドでエントリーウィジェットが変更された場合は 'forced' が設定されている
  • '%W'validation が行われているウィジェットの名前

例えば vcmd に指定するタプルの第 1 要素以降に下記を指定すれば、validation を行う関数には合計5つの引数が渡されることになります。

vcmdの第1要素以降の指定例
'%d', '%i', '%P', '%s', '%S'

従って、validation を行う関数では引数を5つ受け取れるように定義を行う必要があります。

validationを行う関数の定義例
def isOk(action, index, after, before, diff):

もしエントリーウィジェットに 'aiueo' が入力され、'e' の前側に挿入カーソルがある状態で 'x' キーを押下した場合、各引数には下記の値が設定された状態で validation を行う関数が実行されることになります。

  • action1(文字列の挿入が行われたことを表す)
  • index3(第 3 文字目に挿入されたことを表す)
  • after'aiuxeo'(挿入後の文字列)
  • before'aiueo'(挿入前の文字列)
  • diff'x'(挿入された文字列)

こういった引数のデータから、ユーザーがどんな操作を行なったかや、何の文字が挿入されたか、挿入された後の文字列が何であるか等が分かるので、validation を行う関数ではこの引数のデータを用いて文字列が妥当であるかの判断を行うことができます。

ここでは “エントリーウィジェットの作成時”、つまり Entry クラスのコンストラクタ実行時に焦点を当てて解説しましたが、エントリーウィジェット作成後に config メソッドを利用して validatevcmd を設定してもオーケーです。

validation を行う関数を作成する

続いて、validation を行う関数(エントリーウィジェットに入力された文字列が妥当であるかを判断する関数)の作り方について解説していきます。

validation を行う関数は自作する必要があります。ちょっと面倒ですが、その分どのような文字列を妥当であるかを自由自在に自分で決めれるというメリットもあります。

この validation を行う関数を作成する上でポイントになるのは下記の2点です。

  • 引数
  • 返却値

引数

エントリーウィジェット作成するで解説したように、validation を行う関数が受け取る引数は vcmd オプションの指定によって変わります。ですので、vcmd オプションへの指定に応じて validation を行う関数が受け取る引数を設定する必要があります。

返却値

validation を行う関数では、下記のように値を返却(return)するように作成するのが基本です。

  • True:エントリーウィジェットの文字列が “妥当である” 時
  • False:エントリーウィジェットの文字列が “妥当でない” 時

エントリーウィジェットへの文字列の挿入・削除が行われた際に False が返却された場合は、その挿入・削除が拒否されます。True が返却された場合のみ、その挿入・削除がエントリーウィジェットの文字列に反映されます。

ただし、文字列の挿入・削除以外が引き金で validation が行われた際は、文字列の挿入・削除が行われたタイミングでの validation ではないため、False を返却したとしても挿入や削除の拒否が行われないので注意が必要です。

Tcl 関数を作成する

エントリーウィジェット作成するで解説したように、エントリーウィジェットに vcmd を指定することで validate オプションで指定したタイミングで validation を行う関数が実行されるようになります。

ただし、vcmd に指定する必要があるのは、Python 言語で作成した関数ではなく、Tcl 言語で作成した関数の名前になります。つまり、単に Python で作成した関数を指定してもダメです。

MEMO

Tcl とはスクリプト言語の1つです

tkinter の内部(Tcl/Tk)では Tcl 言語が使用されている部分があるので、そこに合わせて Tcl 言語で作成した関数を作成しておく必要があるのだと思います

なので、validation を行うためには vcmd に指定する Tcl 言語の関数を用意する必要があります。

いきなり Tcl 言語の関数を作成するのは難しそうですが、tkinter には register メソッドが用意されており、この register メソッドを実行することで、Python 言語で作成した関数を呼び出す Tcl 言語の関数を作成することができます。

register メソッドはメインウィンドウ(Tk クラス)を含む全ウィジェットに用意されているメソッドになります。さらに、引数には作成した Tcl 言語の関数から呼び出したい Python の関数を指定します。

さらに、register メソッドの返却値は “作成した Tcl 関数の名前” になります。なので、register メソッドの戻り値をそのまま vcmd に指定すれば、validate オプションで指定したタイミングで vcmd に指定した Tcl 関数が実行され、さらにその Tcl 関数から register メソッドに指定した Python 関数が実行されるようになります。

例えばこの章の最初に紹介したスクリプトでは、validation を行う関数(Python の)は下記の isOk になります。

validationを行う関数
def isOk(diff):

さらに、この isOk を基に、下記で register を実行して Tcl 関数を作成しています。register を実行している app はメインウィンドウ(Tk クラスのインスタンス)になります。前述の通り、register メソッドは他のウィジェットにも用意されており、どのウィジェットから実行しても良いと思います。

Tcl関数の作成
tcl_isOk = app.register(isOk)

ここで作成される Tcl 関数が実行された際には、isOk も実行されるようになります。さらに tcl_isOk には、作成した Tcl 関数の関数名が格納されます。

で、この tcl_isOk をエントリーウィジェット作成時に vcmd に指定しています。

エントリーウィジェットの作成
entry = tkinter.Entry(
	app,
	validate='key', # validationを行うタイミング
	vcmd=(tcl_isOk, '%S') # validationを行うTcl関数とその関数の引数
)

validate オプションには 'key' を指定しているので、ユーザーがエントリーウィジェットの文字列の挿入や削除を行なった際に tcl_isOk が実行され、さらにその tcl_isOk から isOk が実行されます。

そして、isOkFalse を返却した際には、その挿入や削除は拒否されるので、プログラマーが意図した文字列のみを入力可能とするエントリーウィジェットを実現できることになります。

スポンサーリンク

validation を行う関数で引数が不要な場合

ここまで validation を行う関数で引数を受け取ることを前提に解説してきましたが、実は引数が不要な場合はもっと簡単に validation 機能を利用することができます。この場合は Tcl 関数を作成する必要もありません。

具体的には、エントリーウィジェット作成時に vcmd にはタプルではなく、validation を行う関数のみを指定するようにすれば、これだけで validation を行う関数が実行されるようになります。

validationを行う関数に引数が不要な場合
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=isOk, # Pythonの関数を指定
	# 略
)

ただし、引数がないのでウィジェット変数の get メソッドなどを利用してエントリーウィジェットの文字列を取得してから妥当性の確認を行う必要があります。

エントリーウィジェット作成するで解説したように、引数を受け取る場合は様々な種類の引数のデータを基に文字列の妥当性確認を行うことができます。例えば “挿入・削除された文字列” や “挿入・削除された後の文字列” を引数で受け取ることができるので、その文字列が妥当でない場合にエントリーウィジェットに反映する “前に” 拒否することができます。

一方で引数がない場合、ウィジェット変数の get メソッドを利用したとしても、得られるデータは “現在のエントリーウィジェットに入力されている文字列” のみです。ユーザーが挿入した文字列などが判らないので、エントリーウィジェットに反映する前に妥当性を確認することが難しいです(というか私にはやり方がわかりませんでした…)。

なので、実用性を考えると、前述で解説した引数ありで validation を行うようにしたほうが良いかなぁと思います。

いろんな validation の例

最後に、ここまで解説してきた内容を踏まえていろんな validation の例を紹介していきたいと思います。

半角英数字のみを入力可能とする

半角英数字のみからなる文字列を妥当と判断するように validation を行うスクリプトの例が下記のようになります。

半角英数字のみを入力可能とする
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(diff):
	
	if not diff.encode('utf-8').isalnum():
		return False

	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%S'),
	textvariable=str_v
)
entry.pack()

app.mainloop()

vcmd に指定するタプルの第1要素に '%S' を指定しているので、ユーザーが挿入・削除した文字列が isOk の引数 diff として渡されるようになります。

あとは isOk の中で、その diffisalnum を実行させて半角英数字かどうかの判断を行い、半角英数字でない場合は False を、それ以外は True を返却するようにしています。

MEMO

isalnum は実行した文字列変数が英数字であるかどうかを判断するメソッドです

ただし文字列が全角の場合はうまく判断できないようなので、事前に UTF-8 形式に encode してからこのメソッドを実行するようにしています。

今回は英数字であるかどうかを判断したいので isalnum を用いましたが、英字のみであるかどうかを判断するために isalpha、数字であるかどうかを判断するために isidigit などというように、判断したい対象に合わせて使用するメソッドを変更することでいろんな判断を行うことができるようになります。

また、このように特定の種類の文字のみを入力可能とするエントリーウィジェットを実現する場合、妥当性を確認するのは “文字列の挿入時” のみで問題ありません。文字列の削除時に確認するのは冗長です。

上記のスクリプトを文字の挿入時のみ妥当性を行うように変更したものが次のようになります。

半角英数字のみを入力可能とする2
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(action, diff):
	
	if action != '1':
		return True

	if not diff.encode('utf-8').isalnum():
		return False

	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%d', '%S'),
	textvariable=str_v
)
entry.pack()

app.mainloop()

vcmd に指定するタプルの第 1 要素に '%d' を指定しているので、is_Ok 実行時には第 1 引数 action に、validation を行う引き金となったアクションを示す文字列が渡されるようになります。

この引数から、文字列挿入時の validation なのか(action'1')、文字列削除時の validation なのか(action'0')が判断できるようになます。

ですので、文字列の挿入時のみ妥当性確認を行いたい場合は、この action'1' 以外の場合は妥当性確認を行わないように validation を行う関数をプログラミングしてやれば良いです。

上記では action'1' 以外の場合は即座に True を返却するようにし、以降の妥当性確認を行わないようにしています。

以降の例でも文字列挿入時のみ妥当性確認を行えば良いものもあるのですが、スクリプトを簡単にするためこのための処理は省略しています。

スポンサーリンク

特定の文字のみを入力可能にする

次は特定の文字のみを入力可能にする validation を行うスクリプトの例になります。

下記では、a, b, c, d, e, f, 0, 1 , @ のみの文字のみを入力可能にするようにしています。

特定の文字のみを入力可能とする
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(diff):
	
	ok = 'abcdef01@'

	for chara in diff:
		if not chara in ok:
			return False

	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%S'),
	textvariable=str_v
)
entry.pack()

app.mainloop()

is_Ok では、まず ok に使用可能な文字からなる文字列を設定し、続いてユーザーが挿入・削除した文字列 diffok に含まれない文字が存在しているかどうかを確認するようにしています(for ループのあたり)。

さらに、ok に含まれない文字が存在している場合は False を、それ以外は True を返却しています。

自分自身で入力可能な文字を細かに指定できるので、汎用性の高い validation を実現することができます。

文字数制限を設ける

次は文字数制限を行うように validation を行うスクリプトの例になります。

下記では、 8 文字以下の文字列のみを入力可能にするようにしています。

文字数制限を設ける
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(after):

	if len(after) > 8:
		return False
		
	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%P'),
	textvariable=str_v
)
entry.pack()

app.mainloop()

vcmd に指定するタプルの第1要素に '%P' を指定しているので、ユーザーによる挿入・削除後の文字列が isOk に引数 after として渡されるようになります。

あとは isOk の中で、その after の文字列長を len 関数で取得し、それが 8 を超える場合に False を、それ以外の場合は  True を返却するようにしています。

文字数に応じてボタンの有効無効を切り替える

次は文字数に応じてボタンの有効無効を切り替える例を紹介します。

下記では文字数が 8 にならないと「実行」ボタンが押せないように制御するスクリプト例になります。

文字数に応じてボタンの有効無効を切り替える
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(after):

	if len(after) == 8:
		button.config(
			state=tkinter.NORMAL
		)
	else:
		button.config(
			state=tkinter.DISABLED
		)

	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%P'),
	textvariable=str_v
)
entry.pack()

button = tkinter.Button(
	app,
	text='実行',
	state=tkinter.DISABLED
)
button.pack()

app.mainloop()

この例では、今までの例とは異なりエントリーウィジェットだけでなくボタンウィジェットも用意しています。さらに、ボタンウィジェット作成時に state=tkinter.DISABLED を指定しているため、アプリ起動時ではボタンは押せない状態(無効状態)になっています。

さらに、is_Ok の中で文字数を取得し、文字数が 8 の場合にはボタンウィジェットの statetkinter.NORMAL に設定し、ボタンが押せる状態(通常状態)にしています(文字数の取得の仕方は文字数制限を設けるで紹介した is_Ok と同様です)

また、文字数が 8 以外の場合には statetkinter.DISABLED に設定しているので、エントリーウィジェットの文字数が 8 以外の場合はボタンが押せないようになっています。 

この validation においては False を返却していないので、入力される文字列に制限はありません。validation では基本的には入力文字列の制限を設けるために使用しますが、今回の例のように “入力文字列が特定の条件を満たしたとき” に何かしらの処理を実行したいような場合にも validation 機能は便利です。

スポンサーリンク

入力不可な文字が入力されている間エントリーの背景色を変更する

次は入力不可な文字が入力されている間にエントリーウィジェットの背景色を変更する例を紹介します。

下記は a, b, c, d, e, f, 0, 1 , @ 以外の文字が入力されている間、エントリーウィジェットの背景色を赤色に設定する例になります。

特例の条件時にエントリーの背景色を変更する
# -*- coding:utf-8 -*-
import tkinter

# 1. validation を行う関数を作成する
def isOk(after, widget_name):

	ok = 'abcdef01@'
	result = True

	# ウィジェット名からウィジェットのオブジェクト取得
	widget = app.nametowidget(widget_name)
	for chara in after:
		if not chara in ok:
			result = False

	if result:
		widget.config(
			bg="white"
		)
	else:
		widget.config(
			bg="red"
		)

	return True

app = tkinter.Tk()

# 2. 1.で作成したコールバック関数をTcl関数として登録する
tcl_isOk = app.register(isOk)

str_v = tkinter.StringVar()

# 3. エントリーウィジェットを作成する
entry = tkinter.Entry(
	app,
	validate='key',
	vcmd=(tcl_isOk, '%P', '%W'),
	textvariable=str_v
)
entry.pack()

app.mainloop()

特定の文字のみが入力されているかどうかは特定の文字のみを入力可能にするで紹介した方法で判断しています。

ただし、このスクリプトでは vcmd の第2要素に '%W' を指定しているので、is_Ok の第2引数 wiget_name として validation を行うウィジェットの名前が渡されるようになります。

このウィジェットの名前 widget_name から validation を行うウィジェットのオブジェクト(つまり entry)を取得し、特例の文字以外が入力されている間はこのウィジェットの bg オプション(背景色)を 'red' に指定するようにしています。

ウィジェットの名前からウィジェットのオブジェクトを取得する際には、上記のスクリプトのように nametowidget メソッドを使用します。

このメソッドはメインウィンドウ(Tk クラス)を含む全ウィジェットに用意されているメソッドです。使える場面もあるので覚えておくと良いと思います。

今回の例の場合はグローバル変数 entry を直接使用しても良いのですが、'%W' から得られる引数からウィジェットのインスタンスを取得できることを紹介するために、このようなスクリプトにしています。

まとめ

このページではエントリーウィジェットで利用できる validation 機能について解説しました!

validation 機能を利用することでユーザーがエントリーウィジェットに挿入・エントリーウィジェットから削除した文字列の妥当性を確認し、これによりプログラマーが意図した文字列のみを入力可能なエントリーウィジェットを実現することができるようになります。

入力される文字列が制限されるので、スクリプトとしても文字列が扱いやすくなります。またユーザーはエントリーウィジェットの操作により入力不可な文字が分かるので、ユーザーにとっても使用しやすいエントリーウィジェットを実現することができます。

特に vcmd に Tcl 関数の関数名を指定する必要があるところがちょっとややこしいですので、register メソッドの戻り値を指定する必要があることはしっかり頭に入れておきましょう!

コメントを残す

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