Tkinterで使われるafterとは?活用方法から注意点まで徹底解説!?
今回はTkinterで使われるafterに関して、活用方法から注意点まで徹底解説いたします。afterを使ってみたい、afterに関して詳しくなりたい方へおすすめです。是非最後までご一読ください。
- そもそもTkinterで使われるafterとは?
- after関数の定義
- after関数で実行されるのは、特定の関数を実行する予約
- 特定の関数を定期実行する方法
- after_cancel関数を利用して、IDに紐づくafter関数の設定情報を削除
- after関数とtime.sleep()の違い
- after関数を利用する際の2つの注意点
- まとめ
- 参考文献
執筆者 - おすすめの記事3選
そもそもTkinterで使われるafterとは?
Tkinterで使われるafterとは、特定の関数を設定する時間分遅らせて実行したり、特定の関数を定期実行するために使われるものを意味します。
別名でafter関数と呼ばれます。Tkinterを活用する上でとても大切な関数になります。
after関数の定義
after関数は
1# ms : どのくらい遅らせてfuncを実行するのかを時間設定する(単位はミリ秒)
2# func : ms経過後に実行する関数
3# args(任意) : funcに渡す引数
4# 戻り値 : ID(after関数の設定情報に紐づくID)
5.after(ms, func, args)
で定義されます。戻り値としてIDが返却されます。IDはafter関数の設定情報に紐づくIDを表し、IDに紐づくafter関数の設定情報を削除する場合などに利用されます。
またafter関数は、全てのWidgetに対応可能です。
Widgetに関しては、【初学者必見!?】Tkinterで使われるlabelの活用方法を徹底解説の「Tkinterの構成要素」でまとめていますので、是非ご確認ください。
例えば、以下のようなコードを作成すると
1import tkinter as tk
2
3class Application(tk.Frame):
4 # hello worldを出力する関数
5 # keyword : dict型
6 def getHelloWorld(self, keyword):
7 print(keyword['text'])
8
9 # after関数に関するサンプル関数
10 def getAfterSample(self):
11 # 5000ms後にself.getHelloWorld関数を実行
12 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
13 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
14 # 第三引数(任意) : 関数実行時に渡される引数
15 # 戻り値 : ID(after関数の設定情報に紐づくID)
16 return self.master.after(5000, self.getHelloWorld, {
17 "text" : "hello world",
18 })
19
20 def __init__(self, master=None):
21 # Windowの初期設定を行う。
22 super().__init__(master)
23 # Windowの画面サイズを設定する。
24 # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
25 self.master.geometry("300x200+120+0")
26 self.getAfterSample()
27
28# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
29if __name__ == "__main__":
30 # Windowを生成する。
31 # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
32 root = tk.Tk()
33 app = Application(master=root)
34 # Windowをループさせて、継続的にWindow表示させる。
35 # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
36 app.mainloop()
以下の画像のように、特定の関数を設定する時間分遅らせて実行(5秒間待つと、hello worldが表示)できます。
after関数で実行されるのは、特定の関数を実行する予約
見出しにも書いた通り、after関数で実行されるのは、特定の関数を実行する予約です。
つまりafter関数を実行するだけでは、特定の関数は実行されません。
特定の関数を実行するためには、mainloop関数が必要になります。
例えば「after関数の定義」で紹介したコード内の、mainloop関数部分をコメントアウトすると、
1import tkinter as tk
2
3class Application(tk.Frame):
4 # hello worldを出力する関数
5 # keyword : dict型
6 def getHelloWorld(self, keyword):
7 print(keyword['text'])
8
9 # after関数に関するサンプル関数
10 def getAfterSample(self):
11 # 5000ms後にself.getHelloWorld関数を実行
12 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
13 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
14 # 第三引数(任意) : 関数実行時に渡される引数
15 # 戻り値 : ID(after関数の設定情報に紐づくID)
16 return self.master.after(5000, self.getHelloWorld, {
17 "text" : "hello world",
18 })
19
20 def __init__(self, master=None):
21 # Windowの初期設定を行う。
22 super().__init__(master)
23 # Windowの画面サイズを設定する。
24 # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
25 self.master.geometry("300x200+120+0")
26 self.getAfterSample()
27
28# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
29if __name__ == "__main__":
30 # Windowを生成する。
31 # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
32 root = tk.Tk()
33 app = Application(master=root)
34 # Windowをループさせて、継続的にWindow表示させる。
35 # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
36 # コメントアウト
37 # app.mainloop()
以下の画像のように、Tkinterの画面は表示されず、hello worldを閲覧できなくなります。
mainloop関数に関して詳しく知りたい場合は、【図解付き!?】Tkinterで使われるmainloopをわかりやすく解説をご確認ください。
特定の関数を定期実行する方法
after関数では、特定の関数を設定する時間分遅らせて実行する以外に、特定の関数を定期実行することができます。
定期実行したい関数内でafter関数を宣言すると、
1# hello worldを出力する関数
2# keyword : dict型
3def getHelloWorld(self, keyword):
4 print(keyword['text'])
5 # 5000ms後にself.getHelloWorld関数を実行
6 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
7 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
8 # 第三引数(任意) : 関数実行時に渡される引数
9 # 戻り値 : ID(after関数の設定情報に紐づくID)
10 return self.master.after(5000, self.getHelloWorld, {
11 "text" : "hello world",
12 })
定期実行が可能になります。
例えば、以下のようなコードを作成すると
1import tkinter as tk
2
3class Application(tk.Frame):
4 # hello worldを出力する関数
5 # keyword : dict型
6 def getHelloWorld(self, keyword):
7 print(keyword['text'])
8 # 5000ms後にself.getHelloWorld関数を実行
9 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
10 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
11 # 第三引数(任意) : 関数実行時に渡される引数
12 # 戻り値 : ID(after関数の設定情報に紐づくID)
13 return self.master.after(5000, self.getHelloWorld, {
14 "text" : "hello world",
15 })
16
17 # after関数に関するサンプル関数
18 def getAfterSample(self):
19 # 5000ms後にself.getHelloWorld関数を実行
20 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
21 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
22 # 第三引数(任意) : 関数実行時に渡される引数
23 # 戻り値 : ID(after関数の設定情報に紐づくID)
24 return self.master.after(5000, self.getHelloWorld, {
25 "text" : "hello world",
26 })
27
28 def __init__(self, master=None):
29 # Windowの初期設定を行う。
30 super().__init__(master)
31 # Windowの画面サイズを設定する。
32 # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
33 self.master.geometry("300x200+120+0")
34 self.getAfterSample()
35
36# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
37if __name__ == "__main__":
38 # Windowを生成する。
39 # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
40 root = tk.Tk()
41 app = Application(master=root)
42 # Windowをループさせて、継続的にWindow表示させる。
43 # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
44 app.mainloop()
以下の画像のように5秒ごとに、hello worldが表示されます。
after_cancel関数を利用して、IDに紐づくafter関数の設定情報を削除
after_cancel関数を利用すると、IDに紐づくafter関数の設定情報を削除できます。
after_cancel関数は
1# 第一引数 : ID(after関数の設定情報に紐づくID)
2# 戻り値 : なし
3.after_cancel(id)
で定義されます。戻り値はありません。
例えば、以下のようなコードを作成すると
1import tkinter as tk
2
3class Application(tk.Frame):
4 # hello worldを出力する関数
5 # keyword : dict型
6 def getHelloWorld(self, keyword):
7 print(keyword['text'])
8
9 # after関数に関するサンプル関数
10 def getAfterSample(self):
11 # 5000ms後にself.getHelloWorld関数を実行
12 # 第一引数 : どのくらい遅らせて第二引数を実行するのかを時間設定する(単位はミリ秒)。
13 # 第二引数 : 第一引数経過後に実行する関数。self.getHelloWorldとする。
14 # 第三引数(任意) : 関数実行時に渡される引数
15 # 戻り値 : ID(after関数の設定情報に紐づくID)
16 return self.master.after(5000, self.getHelloWorld, {
17 "text" : "hello world",
18 })
19
20 # after関数をキャンセルする関数
21 # id : ID(after関数の設定情報に紐づくID)
22 def removeAfterSample(self, id):
23 # 第一引数 : after関数の設定情報に紐づくID
24 self.master.after_cancel(id)
25
26 def __init__(self, master=None):
27 # Windowの初期設定を行う。
28 super().__init__(master)
29 # Windowの画面サイズを設定する。
30 # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
31 self.master.geometry("300x200+120+0")
32
33 id = self.getAfterSample()
34 self.removeAfterSample(id)
35
36# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
37if __name__ == "__main__":
38 # Windowを生成する。
39 # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
40 root = tk.Tk()
41 app = Application(master=root)
42 # Windowをループさせて、継続的にWindow表示させる。
43 # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
44 app.mainloop()
以下の画像のように、IDに紐づくafter関数の設定情報が削除されて、何秒経過してもhello worldは表示されません。
after関数とtime.sleep()の違い
after関数とtime.sleep()は時間を遅らせる観点でみると、とても似ています。しかしプログラムの扱いに関して、明確な違いが存在します。
after関数はプログラムを停止することなく、ボタンクリックなどを受け付けます。
反対にtime.sleep()はプログラムを停止して、ボタンクリックなどを受け付けません。
例えば、以下のようなコードを作成して、time.sleep(3)
箇所をコメントアウトすると
1import tkinter as tk
2import time
3
4class Application(tk.Frame):
5 # helloを出力する関数
6 def getHello(self):
7 # コメントアウト
8 # time.sleep(3)
9 self.master.after(3000, self.getHello)
10 print('hello')
11
12 # time.sleepとafter関数を比較する関数
13 def confirmTimeVsAfter(self):
14 # Windowを親要素としてbutton Widgetを作成する。
15 # command : ボタンをクリックした場合に、実行する関数を設定。self.getHelloとする。
16 # text : テキスト情報
17 # Buttonについて : https://kuroro.blog/python/oFju6EngDtcYtIiMIDf1/
18 button = tk.Button(self.master, command=self.getHello, text='クリック')
19 # Windowを親要素として、button Widgetをどのように配置するのか?
20 # packについて : https://kuroro.blog/python/UuvLfIBIEaw98BzBZ3FJ/
21 button.pack()
22
23 def __init__(self, master=None):
24 # Windowの初期設定を行う。
25 super().__init__(master)
26 # Windowの画面サイズを設定する。
27 # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
28 self.master.geometry("300x200+120+0")
29 self.confirmTimeVsAfter()
30
31# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
32if __name__ == "__main__":
33 # Windowを生成する。
34 # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
35 root = tk.Tk()
36 app = Application(master=root)
37 # Windowをループさせて、継続的にWindow表示させる。
38 # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
39 app.mainloop()
以下の画像のように、after関数が実行される間もボタンクリックでき、helloが表示されます。
反対にtime.sleep(3)
箇所のコメントアウトを外して、self.master.after(3000, self.getHello)
箇所をコメントアウトすると、
1# helloを出力する関数
2def getHello(self):
3- # time.sleep(3)
4+ time.sleep(3)
5- self.master.after(3000, self.getHello)
6+ # コメントアウト
7+ # self.master.after(3000, self.getHello)
8 print('hello')
以下の画像のように、time.sleep()が実行される間はボタンクリックできず、一度にたくさんのhelloが表示されなくなります。
after関数を利用する際の2つの注意点
after関数を利用する上で2点注意すべきことがあります。
after関数を使いすぎると負荷が高くなる
after関数の設定時間が短かったり、after関数で設定する関数の処理が重い場合に、高い負荷がかかってしまい、円滑に処理されなくなる可能性があります。
高い負荷を与えないためにも、
- after関数の設定時間を長めにとる
- after関数で設定する関数の処理を軽くする
を意識して開発する必要があります。
指定する時間に関数が実行されるとは限らない
「after関数で実行されるのは、特定の関数を実行する予約」でも書きましたが、特定の関数を実行するのはmainloop関数になります。
mainloop関数は、その他の関数に対しても処理しなければならないので、負荷がかかっている場合には、after関数の実行が遅れる可能性があります。
多少のずれは起こる前提で、after関数を利用しましょう。
まとめ
- Tkinterで使われるafterとは、特定の関数を設定する時間分遅らせて実行したり、特定の関数を定期実行するために使われるものを意味します。
- 別名でafter関数と呼ばれます。
- 特定の関数を実行するのはmainloop関数