質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

1回答

1079閲覧

tkinter after_func処理が消えない

goki_gottan

総合スコア168

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

0クリップ

投稿2021/02/18 12:21

編集2021/02/18 14:00

tkinterで、canvasの図形を1秒刻みで色換えをしており、その処理を、
after(1000,func)としており、90回くらい繰り返しております。
終わって欲しいタイミングで、
after_cancelを入れているのですが、極たまにafter処理が残っていたのか、思うように止まらないときがあります。
そこで、
while trueを設け、例外処理で、after_cancelをしてエラーとなればafterが消えたと判断し、whileを抜けたとしているのですが、やはり、極たまに起きます。

強制的に削除できないものでしょうか?

def t1()     global after_id def repeat_func(): global after_id        canvasの色変更 frame1.update canvas.update_idletasks() # 描画更新 after_id = frame1.after(500, repeat_func) return     repeat_func for a in b: ある処理     frame1.after_cancel(after_id) after_id=None       thread3=threading.Thread(target=t1) thread3.start()

スレッドを使用しているのは、tkinterGUIを使用して、
for文を使用し、その結果をcanvasで色付けしているためです。

このスレッドが悪さしているということはないでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2021/02/18 12:33

問題を再現できる最低限のコードを提示してください。
goki_gottan

2021/02/18 14:01

修正しました。すみません。 tkinterを使用しており、for文を使うためthreadingを使用しております。 また、その結果をcanvasに反映しており、afterは定期的に図形の色を変更するために使用しております。
teamikl

2021/02/18 16:13

提示されたコードは実行できないので、 出来れば、実行可能なコードの掲載をお願いします。 余分な部分を削るのは良いのですが、必要な部分も削られてるので 最低限、実行可能&問題を再現できる形は残してください。
guest

回答1

0

別スレッドから tkinter の操作自体が、
マルチスレッドで安全な操作ではありません。
処理の内容次第ですが、タイマーを使うか、スレッドどちらかで良いはずです。

  • A: Tkinterのタイマー のみで実装する。

 タイマーで呼び出される処理は、メインスレッド内のイベントループ内で実行されます。
但し、制限として時間の掛かる ループ文はそのまま使えません。
(イベントループを阻害しないように工夫が必要)

  • B: スレッドを使う場合は、Queue 等を使ってメインスレッドへ通知。

 canvas の色変更等、tkinterの操作は、必ずメインスレッド側で行うようにします。
もしくは、after_idle を使うとメインスレッド側で呼び出す事が出来ます。
(完全にスレッドセーフな方法ではありませんが、代案)

  • C: スレッドセーフなtkinter の実装を使う。(外部ライブラリのmttkinter等)

 スレッドのコードと混同してしまうでお勧めはしませんが、
一応、解決案の一つとして提示。


質問に掲載のコードで

repeat_func

関数呼び出しの括弧が無い
関数が呼び出されていない為、after_id は未定義になるはずです。
エラーが出てる場合は、エラー内容も記載してください。

但し、ここは修正したところで別問題が発生するので、
GUIの操作とスレッドで行う処理の分離を検討した方が良いです。

投稿2021/02/18 16:47

編集2021/02/18 16:48
teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

goki_gottan

2021/02/18 22:59

ありがとうございます。 ()は記載わすれです。 おっしゃる通り、色が時間以上に切り替わるときがあり、after関数が複数立ち上がっている感じがします。 図形の色変化はメインでするようにしてみます。ご推察の通り、ループは長い処理です。 そのサブスレッドの変数をメインの受け取り方が分かりません?受け渡し方法教えていただきたいです
teamikl

2021/02/19 01:45

質問のコードではどこに変数の受け渡しがあるのか解りません。 スレッド間の変数の受け渡しは、いくつかありますが queue を使う方法が汎用的です。 詳しくはスレッド間通信等を調べて下さい。 コードの一部が間違ってるとかではなく、おそらくタイマー/スレッドの用法の誤りなので 設計から見直す必要があると思います。 回答に提示したA,B,Cのどの方法が適してるかは具体的な処理内容次第ですが、省略されてるので解りません。 修正依頼に書いたように、まずは実行可能なコードを提示してください。
teamikl

2021/02/19 01:54

Tkinerに限った方法だと、タイマー (after や after_idle) に登録した関数は、 mainloop() から呼び出されるので、通常はメインスレッドで呼び出されます。 これを利用して、サブスレッド→メインスレッドのやりとりに、after_idle を使う事もできます。 (完全にスレッドセーフという訳ではないので注意は必要ですが、比較的簡単な方法)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問