はじめに
第8回では、PythonのGUI(Tkinter)から
XYテーブルを操作できるようになりました。
- 移動量入力
- XY同時制御
- 緊急停止
を とりあえず動かしました
しかし実際の装置では
しかし、ここで多くの人が疑問に思います。
なぜ Thread を使う必要があるのでしょうか?
もし Thread を使わないと、
GUIは簡単に 固まってしまいます。
今回は「GUIが固まる原因と、Threadによる解決方法」を解説します。
GUIプログラムの仕組み
TkinterなどのGUIは
イベントループで動いています。
イメージ
イベント待ち
↓
ボタンが押された?
↓
処理実行
↓
画面更新
↓
イベント待ち
この処理は 1つのスレッドで動いています。
これを
GUIメインスレッド
と呼びます。
GUIが固まる原因
例えば、ボタンを押したときに
モーター制御を直接実行するとします。
def start_xy():
run_motor()
モーター制御は次のような処理です。
forループ
↓
GPIO制御
↓
time.sleep()
↓
数千回繰り返す
この処理は数秒〜数十秒かかります。
問題はここです。
この処理は
GUIスレッドで実行されます。
つまり
GUIスレッド
↓
モーター処理
↓
イベント処理停止
結果
画面更新されない
ボタン押せない
ウィンドウ動かない
つまり
GUIが固まる
Threadで解決する
そこで使うのが
threading.Thread
です。
Threadを使うと
モーター処理を 別スレッドで実行できます。
例
threading.Thread(
target=run_motor,
args=(...)
).start()
すると処理はこう分かれます。
GUIスレッド
↓
画面更新
ボタン操作モータースレッド
↓
GPIO制御
ステップループ
つまり
GUIは操作可能
モーターは裏で動く
という状態になります。
Threadなし
GUI
↓
モーター処理
↓
GUI停止
Threadあり
GUIスレッド
↓
画面更新
ボタン操作モータースレッド
↓
モーター制御
XY同時制御にもThreadが必要
XYテーブルでは
2軸を同時に動かす必要があります。
その場合
XモーターThread
YモーターThread
を作ります。
イメージ
Thread X → Xモーター
Thread Y → Yモーター
これで XY同時移動ができます。
しかしThreadにも問題がある
Threadには問題もあります。
それは
GUIとThreadの通信
です。
例えば
- 現在位置表示
- エラー表示
- 動作完了通知
などです。
GUIスレッド以外から
直接GUIを操作すると
エラー
になることがあります。
解決方法:Queue
そのため次の方法を使います。
queue.Queue()
仕組み
モータースレッド
↓
Queueにメッセージ送る
↓
GUIスレッド
↓
メッセージ受信
↓
画面更新
これは
Python GUI設計の定番パターン
です。
まとめ
今回解説した内容
- GUIはイベントループで動く
- モーター処理は時間がかかる
- 同じスレッドで実行するとGUIが固まる
- Threadを使うとGUIが止まらない
さらに
- Thread通信にはQueueを使う
という設計になります。
次回予告(第9回)
次回は、XYテーブルを
装置として完成させます。
追加する機能
- 原点復帰GUI
- 現在位置表示
- ソフトリミット
これで
本格的なXYテーブルコントローラ
になります。


コメント