CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
こんにちは、吉政創成 菱沼です。
今回も「いちばんやさしいPython入門教室(大澤 文孝氏著) 」を片手に勉強していきます。
「クラス」と「オブジェクト」の概念を学ぶということで、前回はcanvas上にマウスでクリックして円を描くという処理を作りました。
今回はタイマーを使って円を動かすという処理を作っていきます。
前回、最後の方でクリックした場所に円を移動させるという処理を作りましたが、今回は勝手に円が動くというプログラムになるようです。
具体的にどうやるのかといえば、「少しずつ円のX座標を増やしながら書いたり消したりを繰り返す」ことで、例えば右なら右方向に動いているように見える、ということだそうです。
さてそのために使用するのがtkinterのタイマーだそうです。
------
引用P.196
tkinterにはタイマー機能があり、一定時間が経過した後に、指定した関数を実行することができます。タイマーは、tkinterオッジェクトnoafterメソッドを呼び出すことで動き出します。たとえば、
>>> root = tk.Tk()
というように変数rootがtkinterオブジェクトを指している場合、タイマーを動かすには以下のように記述します。
>>>root.after(時間, 実行したい関数)
時間は1000分の1秒単位で指定します。この単位を「ミリ秒」と言います。たとえば「500」と指定した場合は、「0.5秒後に実行する」という意味です。
円が動くようなアニメーションであれば、30(=0.03秒)~10(=0.01秒)程度の微小な値を指定して、そのつど、円を描画する座標を少しずつ変えていくと、動いているように見えます。
-----
ということで、タイマーといってもタイマーという名前ではなく、「after」というメソッドのことのようです。afterメソッドは以下のようなものだそうです。
<afterメソッドでできる処理>
①特定の処理を指定した分遅らせて実行する
②特定の処理をある時間ごとに定期的に実行することができる
<afterメソッドの特徴>
・全ウィジェットのクラスで使用できる
・1回の実行につき1回のみ実行(回数指定はできない)
・使いすぎるとCPUの負荷が高くなる
・mainloop実行中に動くものであるため、必ずしも指定された時間に動くわけではない
<補足:time.sleep>
ところで、一見、afterと同じように使えそうな「time.sleep」というものがあるそうです。
ただ、こちらは指定した秒数分、プログラムを停止させる関数なのだそうで、そもそも動きが違うということです。
・time.sleep(停止させたい秒数):停止している間、ほかの処理を実行できない(mainloopが実行できない)
※import timeが必要
・after:プログラムが停止しないため、ほかの処理を受け付け、実行できる
tkinterはGUIを作ることができるものであるため、ユーザーがボタンをクリックするなどの動作が発生します。そのため、time.sleepを使用すると妙な停止時間が生まれてしまい、ユーザーのストレスになるので、tkinterを使うなら、time.sleepは使用しない方がいいそうです。
参考:Tkinterの使い方:after で処理を「遅らせて」or 処理を「定期的」に実行する
ということで、円を移動するという処理自体は定期的に実行するというものになります。
ただ、①の場合であれば特別な書き方は必要ないのですが、②の定期的に実行するという処理をするためには別の書き方をしてあげないといけないようです。
まずは①を簡単に試してみました。
新たに作った関数の中には画像とテキストを表示させるものを入れています。
最後に、「root.after」で秒数と対象の関数を指定してあげると処理が走ります。
上図では3秒後にnyaという関数で指定されている画像+テキストを表示する、という事になります。
ちなみに、3秒後に1つ目の画像を表示した後、さらにその3秒後(スタートしてから6秒後)に画像を表示させてみるなんてこともやってみました。
これ以外にボタンを押すと別の画像に切り替わるとか、定期的に画像を入れ替えるといった処理もできるようです。タイマーなんかも作れるらしいです。ご興味のある方は以下URLご参照ください。
Pythonのtkinterのcanvasに表示する画像を切り替える(ボタンで入れ替え)
【python】【Tkinter】本格的なタイマーを作ってみた
さて、次に②の定期的に処理を実行するという内容です。まずはサンプルコードから。
直前にあった円を消すという考えは前回までと変わりません。
変わったのは0.01秒後にx座標に+1をするという事になります。これで円は右にぞぞぞっと動いていきます。
ちなみに今回は単純に右に移動させたいだけなので、y座標は変更されないため書かれていませんが、「y = y + 1」を追加すると右斜め下に、「+1」を「-1」に変えると反対側に移動していきます。
では次にもっと速く動かしたいという場合です。
------
引用 P.198
もっと速く円を動かしたいときは、次の二つの方法があります。
①タイマーの間隔を速くする
(中略)いまは「10」に指定していますが、これを「5」にすれば、move関数が0.005秒に1回実行されるようになるので、倍速で動くようになります。
>>>root.after(5, move)
ただし、この方法は、実行される回数が増えてパソコンの負荷が高まるので、あまり小さい値にすべきではありません。
②座標の移動量を増やす
もう1つの方法は、Xの移動量を増やすやりかたです。いまは、
>>>x = x + 1
としてありますが、
>>>x = x + 2
のように2つずつ増やせば、倍速で動くようになります。
----
とのことでした。
ちなみにテキストによれば、「テレビや映画のアニメーションは1秒で24~30コマで動いている」そうで、このレベルにしたいなら「1000÷24≒40程度の値以下に指定する」といいらしいです。これより値が大きい場合は動きがかくかくするとのこと。いろいろ試して遊んでみたいですね。
それでは今回はこちらで終了です。お付き合いいただきありがとうございました。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes