このページでは、Python の tkinter における mainloop
について解説します。
mainloop
は僕もよく使うよ
とりあえずスクリプトの最後で実行してる
mainloop
こそが tkinter の本体と言ってもいいくらい、重要なメソッドだよ
知っていると tkinter でより良い GUI アプリが作れるようになるよ
あなたも mainloop
をおまじないのように使っていませんか?
最初はそれでも良いですが、mainloop
を理解しておくことで、tkinter でよりユーザーが使いやすい GUI アプリの開発や tkinter が上手く動いてくれない時の解決方法を見つけやすくなります。
mainloop
とは
まず mainloop
とは何か?について解説します。
mainloop
の使い方
mainloop
は tkinter の全ウィジェットに用意されたメソッドになります。
どのウィジェットからも実行可能ですが、メインウィンドウから実行させるのが一番一般的だと思います。
mainloop
メソッドの定義は下記のようになります。
mainloop(self, n=0)
引数 n
が指定可能ですが、まずは無視して引数なしで実行して良いです。
戻り値は無し(None
)です。
例えば下記は mainloop
を実行する簡単なスクリプト例になります。
import tkinter
app = tkinter.Tk()
app.mainloop()
スポンサーリンク
mainloop
はループを行うメソッド
mainloop
とはその名の通り「ループ」処理を行うメソッドになります。
mainloop
メソッドを実行すると、mainloop
の中でループ処理が行われます。
基本的にアプリが終了するまで行われる無限ループと考えて良いです。
mainloop
の役割
mainloop
の主な役割は下記の2つです。
- アプリの待機
- イベントの処理
「アプリの待機」はループ処理を行うことで実現しており、「イベントの処理」はそのループの中で実行される処理になります。
この「アプリの待機」と「イベントの処理」についてここから詳しく解説していきます。
mainloop
によるアプリの待機
では mainloop
の主な役割の1つである「アプリの待機」について解説していきたいと思います。
スポンサーリンク
プログラムは最後まで実行されると終了する
まず思い浮かべていただきたいのが「あなたがいつも作っている Python スクリプト」です。
実行すると、スクリプトの最後まで実行されるとプログラムが終了すると思います。
これは tkinter を利用している場合でも一緒です。スクリプトの最後まで実行されるとプログラムが終了してしまいます。
例えば下記のようなスクリプトを実行しても即座にプログラムが終了してしまうことになります。
import tkinter
app = tkinter.Tk()
GUI アプリではアプリの待機が必要
一方で、通常 GUI アプリではユーザーからの操作(ボタン操作やマウス操作など)を受け付けるため・アプリ上に情報を表示させるために、終了させず待機させておくことが必要です。
例えば計算機アプリは、起動すると待機し、その後ユーザーからのマウス操作やキーボード操作により数字の入力や計算の実行を指示されるのを待ちますよね。
こんな感じで自作したアプリも待機させ、ユーザーからの操作を待つことが必要です。
mainloop
を実行すればアプリを待機させられる
mainloop
はそのアプリを待機させる役割を担っています。
なぜ mainloop
によりアプリを待機させることができるかと言うと、mainloop
の中がループ処理になっているからです。
mainloop
のループ処理は、終了ボタンが押されるなど、意図的にアプリが終了しない限り続きます。
ですので、mainloop
を実行するだけで、プログラムが終了するのを防ぎ、アプリを待機させることができるようになります。
mainloop
の実行を忘れててアプリが起動しなくて焦ったことあったよ…mainloop
の実行を忘れると、アプリが起動すらせずプログラムが終了してしまいます(私もよく忘れます…)。
エラーが出ていないのにアプリが全く起動しない場合は、まずは mainloop
を実行しているかどうかを確認しましょう!
でも単に待機させたいだけなら while
でループしちゃえばいいんじゃないの?
例えば下記のスクリプトみたいに!
mainloop
の代わりに自作の無限ループを実行した場合はアプリは起動するでしょうか…?
import tkinter
app = tkinter.Tk()
while True:
pass
いい気づきだね!でも…
とりあえず実行してみ?
プログラムを終了させないだけであれば、確かに上記のスクリプトで実現できます。
ただし、前述の通り、mainloop
の役割には「アプリの待機」だけでなく「イベント処理」もあります。
アプリの画面をスクリーン上に描画するのもこの「イベント処理」で行われます。なので、上記のスクリプトでは「アプリの待機」はできてもアプリの画面を表示するようなことはできません。
mainloop
においてはこの「イベント処理」が行われる点が特に重要です。次はこの mainloop
によるイベントの処理について解説していきたいと思います。
スポンサーリンク
mainloop
によるイベントの処理
では mainloop
によるイベントの処理について解説していきます。
イベントの処理とは
mainloop
の中身は前述の通りループです。そして、そのループの中では「イベントの処理」が行われます。
まず「イベント」とはそのアプリで発生した出来事のことを言います。
tkinter では下記のようなイベントを扱うことができます。
- マウスボタンのクリック
- マウスの移動
- キーボードのキー入力
- ウィジェットの作成・配置・設定変更
「イベントの処理(イベント処理)」とは、そのイベントが発生した時に何かしらの処理(関数)を実行することを言います。
例えば下記のようなものはイベントの処理です。
- マウスボタンのクリックイベントが発生した時(ユーザーがアプリ上でマウスボタンをクリックした時)に関数
click_func
を実行する
どのイベントが発生した時に、どの関数を実行するかは bind
メソッドにより設定可能です。
そして、このイベント発生時に実行される関数は「イベントハンドラ」と呼ばれます。
この辺りは下記ページで解説していますので、イベントについて理解したりイベントを使いこなしたい方は読んでみてください。
Tkinterの使い方:イベント処理を行う前述の通り、どのイベントが発生した時に、どの関数を実行するかは bind
メソッドにより設定可能ですが、もともと tkinter 本体で設定されているイベント処理もあります。
例えばウィジェットの作成や配置・設定変更もイベントとして扱われ、これらを反映してスクリーンに表示する処理はもともと tkinter 本体で設定されているイベントハンドラによって実行されます。
イベントハンドラは mainloop
から実行される
ではこのイベントハンドラがどうやって実行されるかについて解説していきたいと思います。
イベントハンドラは mainloop
の中から実行されます。
mainloop
は単にループするだけでなく、ループの中で下記のような処理を行なっています。
- イベントが発生していないかを確認
- そのイベントに対するイベントハンドラを実行
図で表すとこんな感じです。
これらの処理が無限ループとして実行されます。
mainloop
実行後のほぼ全ての処理はイベント処理として実行されます。ですので、tkinter で開発したアプリの処理のほぼ全ては mainloop
から実行されると考えて良いです。
こういう視点で考えると、mainloop
は tkinter で開発したアプリの本体のように捉えることもできます。
イベントハンドラは mainloop
の中で実行されているため、mainloop
が実行されないとイベント処理は実行されません。
ウィジェット等の表示もイベント処理として実行されるため、たとえウィジェットの作成や配置を行ったとしても、mainloop
を実行しないことにはスクリーン上には表示されないことになります。
これが先ほど示した自作のループでアプリが起動しなかった(アプリの画面が表示されなかった)理由になります。
また mainloop
から実行されたイベントハンドラの処理が終了すると、再び自動的に mainloop
に戻ります。
ですので、一つのイベントに対するイベントハンドラの実行後には、特にプログラマーが意識しなくても、その次に受け付けたイベントに対するイベントハンドラが自動的に実行されることになります。
スポンサーリンク
イベント処理が終わらないと次のイベント処理が出来ない
逆に言うと、イベント処理が終わらないと次のイベント処理が実行されないことになります。
例えば下記のようなスクリプトについて考えてみましょう!
# -*- coding:utf-8 -*-
import tkinter
# ボタンが押された時の処理
def button_click(event):
global label
# ラベルの文字列を変更
label.config(
text="ボタンが押されました"
)
# 10秒間スリープ
import time
time.sleep(10)
# メインウィンドウを作成
app = tkinter.Tk()
app.geometry("200x100")
# ボタンの作成と配置
button = tkinter.Button(
app,
text="ボタン",
)
button.pack()
# ラベルの作成と配置
label = tkinter.Label(
app,
width=20,
height=1
)
label.pack()
# イベント処理の設定
button.bind("<ButtonPress>", button_click)
# メインループ
app.mainloop()
このスクリプトでアプリ上に配置しているのはボタンウィジェットとラベルウィジェットです。
ボタンが押されたときには button_click
関数が行われるようにイベント処理の設定(bind
メソッドによる設定)を行っています。
button_click
関数ではラベルに表示する文字列を「ボタンが押されました」に設定する処理を行っています。さらにその後、time.sleep
関数を使って10秒間スリープするようにしています。
スクリプトを実行してアプリを起動し、ボタンを押すとどうなるでしょうか?
time.sleep
よりも先に label.config
実行してるのに…スクリプトの実行順序と逆に感じるかもしれませんが、実は10秒待たされた後にラベルに「ボタンが押されました」が表示されます。
これは、下記のような順序でイベント処理としてウィジェットの表示が行われるためです。
- ボタンが押されて
mainloop
からイベントハンドラであるbutton_click
関数が実行される button_click
の中でlabel.config
が実行され、「ラベルの設定変更」のイベントが発生するtime.sleep
により10秒間スリープするbutton_click
関数が終了してmainloop
に戻るmainloop
の中で「ラベルの設定変更」のイベントハンドラが実行され、設定変更内容が画面上のラベルに反映される
ポイントは 2. ではイベントが発生するだけで、そのイベントに対するイベントハンドラによる処理は mainloop
に戻ってから 5. で実行されることです。
こんな感じでイベントハンドラの実行は mainloop
でのループ中にしか実行されません。イベントハンドラ実行中は他のイベントに対するイベントハンドラは実行されないのです。
これは、もし他のイベントハンドラの処理の実行時間が長いと、次のイベントに対するイベントハンドラの処理がその分遅くなるということを意味します。
例えばイベントハンドラの処理時間が長いと、ユーザーがボタンを押してもそのボタンに対するイベントハンドラの処理が遅れて実行されることになります。
ユーザーからすると「ボタンを押してもなかなか反応しない」と感じるため、アプリの使用感が悪くなってしまいます。
tkinter ではいかにして mainloop
に処理を戻すかが重要
tkinter でアプリを開発するときは「いかにして mainloop
に処理を戻すか」を意識してプログラミングするようにしましょう!
これにより イベントをこまめに実行できるようになり、ユーザーの使用感を向上させることができます。
例えばイベントハンドラでは下記のような処理は行わないほうが良いです。
- スリープ処理(スリープしている間他のイベントが処理されない)
- 負荷の高い処理(処理している間他のイベントが処理されない)
こういった処理が必要な場合は、まずは下記に置き換えられないかどうかを検討してみてください。
- スリープ処理を
after
メソッドに置き換えられないか - 負荷の高い処理を細かい単位の処理に分解できないか
スリープ処理をafter
メソッドに置き換える
実際に「いかにして mainloop
に処理を戻すか」を考慮した時にどのようにスクリプトを変更すれば良いかを実例を踏まえて説明しておきます。
下記はスリープ処理を用いたタイマーアプリ(1から10を1秒ずつカウントアップしていくアプリ)になります。
# -*- coding:utf-8 -*-
import tkinter
start_flag = False
# タイマー
def timer(count):
global label
global start_flag
if start_flag:
import time
time.sleep(1)
label.config(text=count)
# スタートボタンが押された時の処理
def start_button_click(event):
global start_flag
start_flag = True
for i in range(10):
timer(i + 1)
# ストップボタンが押された時の処理
def stop_button_click(event):
global start_flag
start_flag = False
# メインウィンドウを作成
app = tkinter.Tk()
app.geometry("200x100")
# ボタンの作成と配置
start_button = tkinter.Button(
app,
text="スタート",
)
start_button.pack()
stop_button = tkinter.Button(
app,
text="ストップ",
)
stop_button.pack()
# ラベルの作成と配置
label = tkinter.Label(
app,
width=5,
height=1,
text=0,
font=("", 20)
)
label.pack()
# イベント処理の設定
start_button.bind("<ButtonPress>", start_button_click)
stop_button.bind("<ButtonPress>", stop_button_click)
# メインループ
app.mainloop()
スクリプトは下記のようにアプリを動作させることを考えて実装しています。
- スタートボタンを押すとイベントハンドラ
start_button_click
が実行され、1秒ずつラベルに表示する数字がカウントアップされる(カウントアップはtimer
関数で実行)- 10になったら終了
- ストップボタンを押すとイベントハンドラ
stop_button_click
が実行され、その時点で数字のカウントアップが終了
が、実行してみると全くこのようには動作してくれません。
スクリプトを実行すると下のような画面のアプリが起動します。
ここまでは良いのですが、スタートボタンを押しても全くラベルの数字が変化しません…。
さらにストップボタンを押しても全くアプリが反応してくれません。
10秒経過するとようやくラベルの数字が変化しますが、いきなり10が表示されてしまいます…。
なぜこのような動きになってしまうのでしょうか?
おそらく mainloop
についてしっかり理解している人には理由がわかるはず!
問題はイベントハンドラ start_button_click
にあります(timer
関数も含めて)。
スタートボタンをクリックすると mainloop
の中からイベントハンドラ start_button_click
が実行されますが、この start_button_click
から実行される timer
関数では「1秒間のスリープ処理&ラベルの text
更新」を10回繰り返しています。
つまり、この処理が終わらないと、start_button_click
は終了しないことになり、その間 mainloop
に処理が戻りません。
したがって、ラベルの text
更新が行われても、実際にその更新後のラベルが画面に表示されるのは、次に mainloop
に戻った時、つまりスタートボタンクリック後の10秒後になります(設定更新後のウィジェットへの画面の表示もイベントハンドラとして mainloop
から実行される)。
またストップボタンが押された時に実行されるイベントハンドラ start_button_click
も mainloop
の中から実行されますので、これも同様に mainloop
に処理が戻らないと実行されません。したがってストップボタンを押してもボタンが反応しないように感じられてしまいます。
こんな感じでスリープ処理を行うと、その間イベントハンドラ内で処理が実行されていることになって長い期間 mainloop
に処理が戻りません。ですので、その間イベントハンドラが実行されなくなり、アプリ全体が停止してしまったように感じてしまいます。
ですので、スリープを使わずにとにかく mainloop
に処理を戻すことを意識してプログラミングすることが重要です。
特に tkinter ではスリープの代わりに after
メソッドを使うと良いです。
下記はスリープを使わずに after
メソッドを用いてほぼ同等のタイマーアプリを実現したスクリプトになります。
# -*- coding:utf-8 -*-
import tkinter
start_flag = False
# タイマー
def timer(count):
global label, app
global start_flag
if start_flag and count <= 10:
label.config(text=count)
app.after(1000, timer, count + 1)
# スタートボタンが押された時の処理
def start_button_click(event):
global app
global start_flag
start_flag = True
app.after(1000, timer, 1)
# ストップボタンが押された時の処理
def stop_button_click(event):
global start_flag
start_flag = False
# メインウィンドウを作成
app = tkinter.Tk()
app.geometry("200x100")
# ボタンの作成と配置
start_button = tkinter.Button(
app,
text="スタート",
)
start_button.pack()
stop_button = tkinter.Button(
app,
text="ストップ",
)
stop_button.pack()
# ラベルの作成と配置
label = tkinter.Label(
app,
width=5,
height=1,
text=0,
font=("", 20)
)
label.pack()
# イベント処理の設定
start_button.bind("<ButtonPress>", start_button_click)
stop_button.bind("<ButtonPress>", stop_button_click)
# メインループ
app.mainloop()
ポイントは start_button_click
で実行している下記部分です。
app.after(1000, timer, 1)
after
は、第1引数で指定した時間(ms 単位)分遅らせてから第2引数で指定した関数を実行するメソッドになります(第3引数はその関数に渡す引数)。
詳細は下記ページで解説していますので、after
について詳しく知りたい方はこちらを参考にしてください。
スリープの代わりに after
メソッドを利用することで、イベントハンドラではなく mainloop
で時間の経過を待つことができるようになります。
「遅らせる」という部分がスリープに似ていますが、after
メソッド実行してもその時点で待たされるようなことはありません。上記のように関数を実行するように登録だけして、すぐに after
メソッドは終了します。
つまり、start_button_click
は after
メソッド実行後に即座に終了することになります。したがってスタートボタンを押すとすぐに mainloop
に戻ります。
そして第1引数で指定した時間が経った後に、第2引数で指定した関数 timer
が実行されます。これも mainloop
の中から実行されます。
timer
の中ではラベルの text
の設定を行った後にまた自分自身(timer
)を1秒後に行わせるように after
メソッドを実行しています。これが10秒分カウントアップするまで続けられます。
前述の通り after
メソッドは遅らせて実行する情報の登録を行うだけですぐに終了しますので、timer
関数もすぐに終了して mainloop
に戻ります。
mainloop
に戻れば timer
関数の中で実行された text
の設定更新に対するイベントハンドラがすぐに実行され、ラベルの更新がすぐにアプリの画面に反映されることになります。
またイベントハンドラではなく mainloop
の中で時間が経過することを待つことが可能ですので、ストップボタンがクリックされた時に即座に時間のカウントアップを終了させることも可能です。
つまり、スリープの代わりに after
メソッドを利用することで、下記のことが行えることになりました。
- ラベルの更新を即座に画面に反映
- ストップボタンでカウントアップを即座に終了
こんな感じで、mainloop
に処理を戻すための工夫をしてやることで、よりユーザーが使いやすいアプリを作れるようになります。
そもそも上記2つが行えないとアプリとして機能していないのでバグとも言えます…。mainloop
を理解していないとこういった「アプリの画面が更新されない」「ボタンが効かない」といった問題が発生しやすいので、mainloop
をしっかり理解し、mainloop
にいかにして処理を戻すかを意識しながらプログラミングすることが重要です。
負荷の高い処理を細かい単位の処理に分解する
今度は負荷の高い処理をいかにして mainloop
に戻しながら処理を行うかについて解説します。
# -*- coding:utf-8 -*-
import tkinter
start_flag = False
# 負荷の高い処理
def calc():
global start_flag
for j in range(100000):
if not start_flag:
return
for i in range(1000):
print(i * j)
# スタートボタンが押された時の処理
def start_button_click(event):
global start_flag
start_flag = True
calc()
# ストップボタンが押された時の処理
def stop_button_click(event):
global start_flag
start_flag = False
# メインウィンドウを作成
app = tkinter.Tk()
app.geometry("200x100")
# ボタンの作成と配置
start_button = tkinter.Button(
app,
text="スタート",
)
start_button.pack()
stop_button = tkinter.Button(
app,
text="ストップ",
)
stop_button.pack()
# イベント処理の設定
start_button.bind("<ButtonPress>", start_button_click)
stop_button.bind("<ButtonPress>", stop_button_click)
# メインループ
app.mainloop()
スクリプトは下記のようにアプリを動作させることを考えて実装しています(負荷の高い処理を実行したいだけなので意味のない計算をしています…)。
- スタートボタンを押すとイベントハンドラ
start_button_click
が実行され、ループの中で計算処理を実行(計算処理はcalc
関数で実行) - ストップボタンを押すとイベントハンドラ
stop_button_click
が実行され、その時点で計算処理を終了
が、実行してみるとストップボタンが効きません。
これは calc
関数がイベントハンドラ内で実行されている& calc
関数の処理負荷が高くて実行時間が長いため、その間 mainloop
に処理が戻らないためです。
負荷の高い処理をイベントハンドラで実行すると、他のイベントハンドラが実行されずにアプリ全体が停止したように感じてしまいます。
こういった負荷の高い処理は、細かい単位の処理に分解できないかどうかを検討すると良いです。そして、その分解した細かい単位の処理の実行が完了するたびに、mainloop
に戻すように制御します。
上記スクリプトの計算処理を細かい単位に分解して実行するようにしたスクリプトが下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
start_flag = False
# 負荷の高い処理
def calc(j):
global start_flag
global app
if start_flag:
for i in range(1000):
print(i * j)
if j < 100000:
app.after(1, calc, j + 1)
# スタートボタンが押された時の処理
def start_button_click(event):
global start_flag
global app
start_flag = True
app.after(1, calc, 0)
# ストップボタンが押された時の処理
def stop_button_click(event):
global start_flag
start_flag = False
# メインウィンドウを作成
app = tkinter.Tk()
app.geometry("200x100")
# ボタンの作成と配置
start_button = tkinter.Button(
app,
text="スタート",
)
start_button.pack()
stop_button = tkinter.Button(
app,
text="ストップ",
)
stop_button.pack()
# イベント処理の設定
start_button.bind("<ButtonPress>", start_button_click)
stop_button.bind("<ButtonPress>", stop_button_click)
# メインループ
app.mainloop()
calc
関数の中で1度に全ての計算処理を行うのではなく、i
に対するループだけを行うように処理を分解しています。
さらに calc
関数の最後で j
を +1
して再度 calc
を実行するように after
メソッドを実行しています(これにより j
に対するループを実現しています)。
これにより i
に対するループが終了すればイベントハンドラの処理も一旦終了し、mainloop
に処理が戻るようになります。
したがって、ストップボタンが押されていればその mainloop
に戻ったタイミングでストップボタンによる処理の終了を行うことができるようになっています。
こんな感じで処理を小さな単位に分解し、分解した処理が終わるたびに mainloop
に戻るようにしてやることで、他のイベント処理を行いながら負荷の高い処理を実行することができるようになります。
そしてこれによりユーザーの使用感を向上させることができます。
mainloop
関連の陥りやすい問題
最後に、ここまでの解説を踏まえ、mainloop
関連の陥りやす問題をいくつか紹介しておきます。これらは mainloop
をしっかり理解していれば解決できる問題です。
スポンサーリンク
アプリの画面が全く表示されない
アプリの画面やウィジェットは mainloop
の中でもともと tkinter に用意されているイベントハンドラが処理されることによって表示されます。
したがって mainloop
を実行しないとアプリの画面やウィジェットは表示されません。
エラーが出ていないのにアプリの画面が一切何も表示されない時は、まずは mainloop
を実行しているかどうかを確認してみましょう!
mainloop
の後ろに記述した処理が実行されない
mainloop
はアプリが起動している間に実行される無限ループです。
ですので、mainloop
の後ろに処理を記述しても、アプリが終了しないと実行されません。
import tkinter
app = tkinter.Tk()
app.mainloop()
print("このメッセージはアプリ終了するまで表示されません")
mainloop
実行前に処理が記述できないかどうかをまず検討し、無理そうであればその後イベントを発生させ、イベントハンドラの中で処理を実行するようにしましょう!
逆にアプリ終了後に行いたい処理は mainloop
の後ろで実行しても良いです。
ウィジェットの表示が更新されない
config
メソッド等でウィジェットの設定を行っても、config
メソッド実行時にその設定が画面に反映されるわけではありません。
config
メソッド実行時に行われるのは設定の変更だけで、その設定が画面上に反映されるのは次に mainloop
に戻った時になります。
したがって、config
メソッド実行後に負荷の高い処理を行ってイベントハンドラの処理が続くと、その間は mainloop
に処理が戻らず、ウィジェットの表示が更新されないことになります。
config
メソッドでウィジェットの設定変更直後にその設定を画面上に反映したい場合は、config
メソッド実行直後に mainloop
に処理が戻るようにイベントハンドラの作りを工夫してみましょう!
スポンサーリンク
ボタンがすぐに効かない
これも「ウィジェットの表示が更新されない」と同じ考え方です。
ボタンクリック時に実行するイベントハンドラも mainloop
の中から実行されますので、他のイベントハンドラで負荷の高い処理を実行していたりすると、その間 mainloop
に処理が戻らないのでボタンをクリックしてもそのイベントハンドラが実行されません。
そのためボタンが効かないようにユーザーは感じてしまいます。
イベントハンドラがこまめに実行できるように、負荷の高い処理も細かい処理に分割し、こまめに mainloop
に処理が戻るように工夫してみましょう!
まとめ
このページでは tkinter の mainloop
について解説しました!
mainloop
の主な役割は下記の二つです。
- アプリの待機
- イベントの処理
アプリの待機ができないとアプリの画面がすぐに消えてしまいます(そもそもアプリ画面が表示されない)。
また tkinter の処理はほぼイベントの処理として扱われるため、イベントの処理ができないとアプリの画面の更新やボタンクリック等のイベントに対する処理も行えません。
tkinter のアプリ開発でボタンの反応やウィジェットの更新タイミングが遅い時は、まずご自身のスクリプトで mainloop
に処理が戻っているのかを確認するのが良いと思います。
また mainloop
を理解していれば、よりユーザーの使用感を向上したアプリ作成もできるようになります!
mainloop
について理解し、ぜひ mainloop
を意識したアプリ開発に挑戦してみてください!
tkinterの初心者です。説明がとてもわかりやすいです。
sleepをafterに置き換えたタイマーアプリ”のコードですが、下記の誤記ではないでしょうか?
7 def timer(count):
8 global label, app
9 global start_flag
10
11 if start_flag and count <=10:
12 label.config(text=count)
13 app.after(1000, timer, count + 1)
匿名さん
コメントありがとうございます!
ご指摘の通り、誤記でしたので早速修正させていただきました。
気づいていなかったので大変助かりました!ありがとうございます!
また何かありましたら気軽にコメント頂ければと思います!
tkinterの初歩的な記事が見つからなかったので、大変勉強になりました。
ありがとうございます。
ウェブサイトデザインも見やすく最高です!
ますさん
コメントりがとうございます!
そう言っていただけると嬉しいです。この記事書いた甲斐がありました!
確かに tkinter の初心者向けの記事って少ないんですよね…。
私のサイトで初心者向けの記事をどんどんアップしていこうと思いますので、また不明点などありましたら覗いてみていただけると幸いです。