このページでは tkinter におけるウィジェット変数(Widget 変数・制御変数)について解説していきたいと思います。
Contents
ウィジェット変数(Widget 変数)
まずはウィジェット変数がどのような変数であるかについて解説していきます。
ウィジェット変数は “ウィジェットと連動する変数”
ウィジェット変数は、「ウィジェットと連動する変数」です。別名で「制御変数(Control Variable)」とも呼ばれます。
ウィジェットに “ウィジェット変数” を設定することで、そのウィジェットの表示を動的に変化させたり、そのウィジェットへの入力を動的に取得したりすることができます。つまり、変数とウィジェットが “連動する” ようになります。
例えば、エンリーウィジェットにウィジェット変数を設定しておけば、エントリーへの入力内容が変更された際に、動的にそのウィジェット変数の内容も変更されます。
また、チェックボタンウィジェットにウィジェット変数を設定しておけば、チェックの有無に応じてウィジェット変数の内容が動的に変更されます。
さらに、ラベルウィジェットにウィジェット変数を設定しておけば、そのウィジェット変数の内容が変更された際に、ラベルの表示内容も動的に変更されます。
スポンサーリンク
ウィジェット変数と通常の変数との違い
ウィジェット変数と通常の変数との1番の違いは、変数が「ウィジェットと連動する」かどうかです。
ウィジェット変数はウィジェットに設定しておくことでウィジェットと連動してくれますが、通常の変数では連動してくれないので自身で変数やウィジェットの更新をプログラミングする必要があります。
このあたりを踏まえて、通常の変数とウィジェット変数の違いを実際のスクリプトで確認していきたいと思います。
ここでは、「ボタンが押された回数をラベルに表示するアプリ」を作成する例で確認していきたいと思います。
ウィジェット変数を使用せずに通常の変数だけでこれを実現する場合、スクリプトしては例えば下記のようなものになります。
# -*- coding:utf-8 -*-
import tkinter
# ボタンが押された回数を初期化
count = 0
def updateCount():
global label
global count
# ボタンが押された回数を更新
count = count + 1
# ラベルを新しいcountで更新
label.config(
text=str(count)
)
app = tkinter.Tk()
label = tkinter.Label(
app,
text=str(count)
)
label.pack()
button = tkinter.Button(
app,
text="ボタン",
command=updateCount
)
button.pack()
app.mainloop()
ポイントは、ボタンが押された時に実行される関数 updateCount
です。
この updateCount
では、ボタンが押された回数 count
を +1
し、さらにそれをラベルウィジェットの text
に設定しています。この “ラベルウィジェットへの設定を行わないとラベルが更新されない” ところがポイントです。
通常の変数ではウィジェットと連動しないので、変数の内容に合わせてウィジェットの設定を更新したいような場合は自身でプログラミングしてウィジェットの設定を行う必要があります。
一方で、ウィジェット変数を使用した場合は下記のようなスクリプトとなります。
# -*- coding:utf-8 -*-
import tkinter
def updateCount():
global label
# ボタンが押された回数を更新
new_count = int(count.get()) + 1
count.set(str(new_count))
app = tkinter.Tk()
count = tkinter.StringVar()
count.set('0')
label = tkinter.Label(
app,
textvariable=count
)
label.pack()
button = tkinter.Button(
app,
text="ボタン",
command=updateCount
)
button.pack()
app.mainloop()
count
がウィジェット変数になります。
こちらも updateCount
関数でボタンの押された回数を更新していますが、更新先はウィジェット変数 count
だけです。
これだけでラベルの表示も自動的に更新されます。
これはウィジェット変数がウィジェットと連動しているからで、ウィジェット変数の内容が更新されれば、そのウィジェット変数を設定しているウィジェットも自動的に更新されます。
こんな感じで、ウィジェットと連動する変数が「ウィジェット変数」になります。
ウィジェット変数の種類
このウィジェット変数には下記の4種類が存在します。
StringVar
IntVar
DoubleVar
BooleanVar
これらは全て tkinter に用意されたクラスになります。つまり、ウィジェット変数とはこれらのクラスのインスタンス(オブジェクト)です。このページではこれらのクラスをひっくるめて “ウィジェット変数クラス” と呼ばせていただきます。
これらのクラスの違いは、変数で扱うデータです。各クラスのウィジェット変数が扱うデータは下記のようになります。
StringVar
:文字列を扱うIntVar
:整数を扱うDoubleVar
:浮動小数点数を扱うBooleanVar
:真偽値(True
/False
)を扱う
ウィジェット変数の使い方
ウィジェット変数を利用する際に行う基本的な処理は下記の4つになると思います。
- ウィジェット変数を作成する
- ウィジェットにウィジェット変数を設定する
- ウィジェット変数からデータを取得する
- ウィジェット変数にデータを設定する
スポンサーリンク
ウィジェット変数を作成する
ウィジェット変数は、前述の下記の4種類のクラスのコンストラクタを実行することで作成することができます。
StringVar
:文字列を扱うIntVar
:整数を扱うDoubleVar
:浮動小数点数を扱うBooleanVar
:真偽値(True
/False
)を扱う
前述の通り、各クラスで扱うデータが異なるため、ウィジェット変数で扱いたいデータに応じて実行するコンストラクタを選択する必要があります。例えば整数を扱う場合は IntVar()
を実行してウィジェット変数を作成します。
下記はこの4種類全てのウィジェット変数を作成するスクリプト例になります。
str_v = tkinter.StringVar()
int_v = tkinter.IntVar()
double_v = tkinter.DoubleVar()
boolean_v = tkinter.BooleanVar()
各コンストラクタの定義は下記のようになっています。
def __init__(self, master=None, value=None, name=None):
self
を除く各引数では、それぞれ下記を指定します。
master
:親ウィジェットvalue
:初期値name
:名前(変数名ではない)
master
が省略された場合は自動的にメインウィンドウが親ウィジェットに設定されます。
name
が省略された場合は PY_VARx
(x
は整数)が自動的に名前として設定されます。ただおそらくこの名前を利用することはほぼない(print
で表示するくらい?)と思いますので設定の必要性は低いです。
ということで設定しておいた方が良いのは value
くらいかなぁと思います。ただ、この value
を指定しなくても、ウィジェット変数作成後に後述で紹介する set
メソッドで設定することも可能です。
value
を指定しなかった場合、各ウィジェット変数の初期値は下記のように設定されます。
StringVar
:""
IntVar
:0
DoubleVar
:0.0
BooleanVar
:False
ウィジェットを一つも作成していない状態でウィジェット変数クラスのコンストラクタを実行するとエラーが発生するので注意してください。
ウィジェットにウィジェット変数を設定する
続いて、連動させたいウィジェットとウィジェット変数を関連づけるために、ウィジェットに対してウィジェット変数の設定を行います。
ウィジェットにはコンストラクタ実行時や config
メソッド実行時に下記のオプションを指定できるものがあります。
textvariable
variable
textvariable
textvariable
は主に “ウィジェットの表示テキストをウィジェット変数と連動させたい場合” に設定します。
下記はラベルウィジェットへの textvariable
の設定例になります。
# ウィジェット変数を作成
str_v = tkinter.StringVar()
# ラベルウィジェットにウィジェット変数を設定
label = tkinter.Label(
app, # appはメインウィンドウ
textvariable=str_v
)
label.pack()
上記のようにラベルウィジェットに textvariable
を設定すれば、ウィジェット変数と str_v
とラベルウィジェット label
が連動するようになります。
より具体的には、str_v
が変化した際には label
の表示内容がその変化後の str_v
に自動的に更新されます。
variable
variable
は主に “ウィジェットの設定内容をウィジェット変数と連動させたい場合” に設定します。
例えばチェックボタンウィジェットに variable
を設定しておくことで、チェックの有無の切り替えに連動して variable
が保持しているデータが変化します。
下記はチェックボタンウィジェットへの variable
の設定例になります。
# -*- coding:utf-8 -*-
import tkinter
app = tkinter.Tk()
boolean_v = tkinter.BooleanVar()
label = tkinter.Label(
app,
textvariable=boolean_v
)
label.pack()
check = tkinter.Checkbutton(
app,
variable=boolean_v,
text="チェックボタン"
)
check.pack()
app.mainloop()
上記のようにチェックボタンウィジェットに variable
を設定すれば、ウィジェット変数と boolean_v
とチェックボタンウィジェット check
が連動するようになります。
より具体的にはチェックボタンウィジェット check
へのチェックの有無が変化した際には、boolean_v
の値が True
or False
に自動的に変化します。
この boolean_v
が自動的に変化する様子が確認できるようにラベルウィジェット label
の textvariable
に boolean_v
を設定しています。
ラベルウィジェットと boolean_v
が連動し、boolean_v
が変化するたびに、つまりチェックボタンウィジェットへのチェックの有無が変化するたびに表示内容が変化する様子が確認できると思います。
textvariable
と variable
の違いはチェックボタンウィジェットが分かりやすいかなぁと思います。
textvariable
ではチェックボタンウィジェットの「表示テキスト」がウィジェット変数と連動することになります。
一方で、variable
ではチェックボタンの「チェックの有無」がウィジェット変数と連動することになります。
ウィジェット変数からデータを取得する
ウィジェット変数のデータを取得したい場合は、ウィジェット変数クラスに用意された get
メソッドを利用します。
get
メソッドの定義は下記のようになります。実行すればウィジェット変数が保持しているデータを取得することができます。
def get(self):
例えば下記スクリプトでは、ボタンが押された時にチェックボタンのチェックの有無の状態 get
で取得し、結果を print
で出力する例になります。
# -*- coding:utf-8 -*-
import tkinter
def get_check():
check = boolean_v.get()
if check:
print("チェックされています")
else:
print("チェックされていません")
app = tkinter.Tk()
boolean_v = tkinter.BooleanVar()
check = tkinter.Checkbutton(
app,
variable=boolean_v,
text="チェックボタン"
)
check.pack()
button = tkinter.Button(
app,
text="ボタン",
command=get_check
)
button.pack()
app.mainloop()
スポンサーリンク
ウィジェット変数にデータを設定する
ウィジェット変数はウィジェットと連動して自動的にデータが設定されることもありますが、ウィジェット変数にスクリプトからデータを設定することも可能です。
この際にはウィジェット変数クラスに用意された set
メソッドを利用します。
set
メソッドの定義は下記のようになります。引数 value
には各クラスで扱うデータの形式に合わせて指定します。
def set(self, value):
set
メソッドを実行することで、ウィジェット変数が保持しているデータが変化します。さらに、ウィジェットにウィジェット変数を設定しておけば、ウィジェット変数の変化に連動してウィジェットの表示テキストや設定が変化します。
例えば下記はチェックボタンのチェックの有無を set
メソッドで切り替えるスクリプト例になります。もちろん set
だけでなくチェックボタンのクリックでチェックを切り替えることも可能です。
# -*- coding:utf-8 -*-
import tkinter
def switch_check():
check = boolean_v.get()
if check:
boolean_v.set(False)
else:
boolean_v.set(True)
app = tkinter.Tk()
boolean_v = tkinter.BooleanVar()
check = tkinter.Checkbutton(
app,
variable=boolean_v,
text="チェックボタン"
)
check.pack()
button = tkinter.Button(
app,
text="ボタン",
command=switch_check
)
button.pack()
app.mainloop()
ウィジェット変数の使いどころ
最後にウィジェット変数の使いどころを紹介しておきます。
ウィジェットと変数を連動させたい時
これはここまでの解説でも紹介してきたウィジェット変数の使いどころですね!
特にチェックボタンやラジオボタンなどでは、チェックの有無やラジオボタンのどのボタンが選択されているかに応じて処理を切り替える必要がありますので、コレらの情報を取得するためにウィジェット変数を利用することが多いです。
スポンサーリンク
ウィジェット同士を連動させたい時
また、異なるウィジェットに同じウィジェット変数を設定することで、そのウィジェット同士を連動させるようなことも可能です。
例えば下記では一方のチェックボタンのチェックの有無を切り替えると他方のチェックボタンも連動して切り替わるスクリプト例になります。
# -*- coding:utf-8 -*-
import tkinter
app = tkinter.Tk()
boolean_v = tkinter.BooleanVar()
check1 = tkinter.Checkbutton(
app,
variable=boolean_v,
text="チェックボタン1"
)
check1.pack()
check2 = tkinter.Checkbutton(
app,
variable=boolean_v,
text="チェックボタン2"
)
check2.pack()
app.mainloop()
おそらくこの目的でウィジェット変数を利用するケースで一番多いのは下記のような「ラジオボタンウィジェット」同士の連携だと思います。
# -*- coding:utf-8 -*-
import tkinter
app = tkinter.Tk()
int_v = tkinter.IntVar()
radio1 = tkinter.Radiobutton(
app,
variable=int_v,
value=1,
text="ラジオボタン1"
)
radio1.pack()
radio2 = tkinter.Radiobutton(
app,
variable=int_v,
value=2,
text="ラジオボタン2"
)
radio2.pack()
label = tkinter.Label(
app,
textvariable=int_v,
)
label.pack()
app.mainloop()
ラジオボタンの特徴は「グループ内のボタンが1つのみ選択できるボタン」である点です。そして、tkinter でこれを実現するのがウィジェット変数です。
ラジオボタンでは、ボタンが選択されると variable
が各ボタンに設定されている value
のデータに自動的に変化します。
さらに各ボタンは、value
と variable
のデータが一致しているもののみが “選択中の見た目” に自動的に変化します。つまりそれぞれのラジオボタンに異なる value
を設定しておけば、違うボタンが選択されると value != variable
となり自動的に選択が外れます。
なので、複数のラジオボタンそれぞれに異なる value
を設定し、さらに variable
に同じウィジェット変数を設定しておけば、あとはラジオボタンとウィジェット変数が連動し、それらのボタンの1つのみが選択可能なラジオボタンとして機能するようになります。
ウィジェット変更時に処理を実行したい時
また、ウィジェット変数を用いてウィジェットに対して操作が行われたときに特定の関数やメソッドを実行させるようなことも可能です。
例えばチェックボタンのチェックの有無が切り替えられた時や、エントリーの入力文字列が変更された際に、自動的に特定の処理を実行させるようなことができます。
trace_add
このようにウィジェットに対する操作に対して自動的に特定の処理を実行させたい場合には、あらかじめ下記の trace_add
を実行しておく必要があります。
def trace_add(self, mode, callback):
trace_add
は実行したウィジェット変数に対する mode
で指定した動作が行われたときに callback
で指定した関数もしくはメソッドが自動的に実行されるように設定を行うメソッドになります。
trace_add
の mode
mode
で指定可能な動作は下記の3つになります。
'write'
:ウィジェット変数のデータが変更された'read'
:ウィジェット変数のデータが取得された'unset'
:ウィジェット変数が破棄された
mode
に 'write'
を設定しておけば、ウィジェットに対して操作が行われた際に、そのウィジェットと連動するウィジェット変数のデータが変更され、自動的に callback
で指定した関数やメソッドが実行されるようになります。
他にも 'read'
を設定しておくことでウィジェット変数のデータが取得された際に自動的に特定の処理を実行させるようなことも可能です。
mode
には複数を同時に指定することも可能で、この場合は下記のようにタプル形式で指定します。
# vはウィジェット変数クラスのインスタンス
v.trace_add(('write', 'read', 'unset'), callback)
trace_add
の callback
callback
には前述の通り自動的に実行されるようにしたい関数やメソッドを指定します。これらの関数やメソッドでは、下記のように引数を取る必要があります。
def callback(arg1, arg2, arg3):
def callback(self, arg1, arg2, arg3):
各引数の意味は下記のようになります。ポイントは self
引数を3つ分受け取る必要があるところです。
arg1
:mode
で指定した動作が発生したウィジェット変数の名前arg2
:すみません、この引数の意味がわかりませんでした…arg3
:発生した動作('write', 'read' or 'unset'
)
trace_add
の利用例
下記が trace_add
の利用例になります。
# -*- coding:utf-8 -*-
import tkinter
def callback(arg1, arg2, arg3):
print(arg1 + 'に' + arg3 + 'が発生しました')
def read_func():
# 'read'を発生させる
print(str_v.get())
def unset_func():
global str_v
# 'unset'を発生させる
str_v = None
app = tkinter.Tk()
str_v = tkinter.StringVar()
entry = tkinter.Entry(
app,
textvariable=str_v,
width=10
)
entry.pack()
button = tkinter.Button(
app,
text="取得",
command=read_func
)
button.pack()
button = tkinter.Button(
app,
text="破棄",
command=unset_func
)
button.pack()
# str_vに動作が発生したときにcallbackを実行させるように設定
str_v.trace_add(('write', 'read', 'unset'), callback)
app.mainloop()
下記が行われると関数 callback
が実行されるようになっています。
- エントリーウィジェットの文字列が変更された時(
'write'
が発生) - 「取得」ボタンが押された時(
read_func
の中でget
メソッドが実行され、この時に'read'
が発生) - 「破棄」ボタンが押された時(
unset_func
の中でstr_v = None
が実行され、GC が動作して'unset'
が発生)
まとめ
このページでは tkinter における「ウィジェット変数」について解説しました!
ウィジェット変数は「ウィジェットと連動する変数」です。ウィジェットと連動するというところが通常の変数と異なります。
ウィジェット変数を用いることで下記のようなことを簡単に実現することができます。
- ウィジェットと変数を連動させる
- ウィジェット同士を連動させる
- ウィジェット変更時に処理を実行する
特にチェックボタンやラジオボタン等を利用する時にはこのウィジェット変数の利用が必須になります!是非これらのウィジェットを利用しながらウィジェット変数への理解を深めてみてください!