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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3291閲覧

2次元セルオートマトンのエラー

suugaku_nyumon

総合スコア37

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/12/03 13:58

編集2018/12/03 13:59

質問内容

Python3.7.1を使っています。下のコードは、2次元セルオートマトンです。これを実行しようとすると、attributeエラーが出てきます。そこでtkinterのupdateとupdate_idletasksを入れることで解決しようと思っていましたが、どのようにダウンロードすればよいか分かりません。教えていただけると嬉しいです。

コード

from tkinter import * import time import tkinter as tk #■配列の宣言 def array2(N1,N2): return [[0 for j in range(N2)]for k in range(N1)] def array3(N1,N2,N3): return [array2(N2,N3)for k in range(N1)] #■セルの初期設定 def initdt(N): A=array3(2,31,31); A[0][15][15]=N-1 return A #■セルオートマトンの実行 def execCell(A,i1,i2,Mod): for i in range(1,30): for j in range(1,30): T=(A[i1][i][j-1]+A[i1][i][j+1]+A[i1][i-1][j]+A[i1][i+1][j]) A[i2][i][j]=T % Mod #■セルの位置決めとIDの設定 def drawCell(canvas,A,k): x2=0 CID=array2(31,31) for i in range(1,30): x1=x2 x2=x1+10 y2=0 for j in range(1,30): y1=y2 y2=y1+10 CID[i][j]=canvas.create_rectangle(x1,y1,x2,y2,fill='black') return CID #■セルの色設定 def modifyCell(canvas,A,k,CID): CL=['black','#FFFF00','#ff0000','#00ff00','#0000FF'] for i in range(1,30): for j in range(1,30): canvas.itemconfig(CID[i][j],fill=CL[A[k][i][j]]) canvas.itemconfig(CID[i][j],outline=CL[A[k][i][j]]) #■Tk初期設定 def initTk(): tk=Tk(); tk.title("2D Cell Automaton"); tk.resizable(0,0) return tk #■待ち処理等 def wait(): tk.update_idletasks() tk.update() time.sleep(0,2) #■画面キャプチャ用 def leftMouseDown(event): global canvas, A,k,CID modifyCell(canvas,A,k,CID) execCell(A,k,1-k,5) k=1-k #■実行メイン A=initdt(5) root=initTk() canvas=Canvas(root,width=290,height=290,highlightthickness=0) canvas.pack() root.update() CID=drawCell(canvas,A,0) k=0 while 1: modifyCell(canvas,A,k,CID) execCell(A,k,1-k,5) wait() k=1-k

エラーメッセージ

Traceback (most recent call last): File "2dcell.py", line 65, in <module> wait() File "2dcell.py", line 45, in wait tk.update_idletasks() AttributeError: module 'tkinter' has no attribute 'update_idletasks'

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

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

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

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

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

guest

回答2

0

ベストアンサー

can110さん回答コメントへの補足です。

_tkinter.TclError: invalid command name ".!canvas"

と表示されますが、一体これは何が原因なのでしょうか?

ウィンドウの×ボタンをクリックするとTcl/Tk側の動作によりウィンドウを破棄する処理が動き始めますが、ご質問のプログラムは「Tcl/Tkのウィンドウの状態を無視して無条件に画面更新コマンドを発行し続ける」という制御上の問題があります。この問題がcan110さんが言っておられる「アニメーション処理のお行儀が悪い」に該当すると思います。

tkinterに限らずイベントループを基本メカニズムとするようなGUIライブラリーにおいては「イベントが何か起こったらそれに応じてしかるべき処理をする」という構造とすべきです。

無限ループにより行っている画面更新処理をコールバック関数として別途定義し、コールバックを0.2秒経過したら呼び出すようにTcl/Tkへ登録するという考え方にするのがよいと思います。それにはafterメソッドを使えばよいでしょう。

最小限の変更のみ施してみますとこんな感じになります。

python

1... 省略 2 3#def wait(canvas): 4# ... この関数は使わない ... 5 6... 省略 7 8# ■実行メイン 9A = initdt(5) 10root = initTk() 11canvas = Canvas(root, width=290, height=290, highlightthickness=0) 12canvas.pack() 13# root.update() # 不要 14CID = drawCell(canvas, A, 0) 15k = 0 16 17 18def animate(): 19 global k 20 modifyCell(canvas, A, k, CID) 21 execCell(A, k, 1 - k, 5) 22 # wait(canvas) # 使わない 23 k = 1 - k 24 root.after(200, animate) # 0.2秒経過したら再度この関数を起動する 25 26 27root.after(200, animate) # 初回のコールバック登録 28root.mainloop()

実際に動かしてみるとウィンドウを閉じた後で実行時例外は起きなくなりました。

投稿2018/12/03 16:21

編集2018/12/03 17:07
KSwordOfHaste

総合スコア18394

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

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

suugaku_nyumon

2018/12/03 16:33

ありがとうございます。 初めて遭遇するエラーで困っていたので助かりました。
KSwordOfHaste

2018/12/03 17:07

回答に書いた修正は(中身を詳しくみなくても)大変容易だったのですが、それはご質問のコードが適切な単位で関数化されていて今回のような制御の変更にも楽に対応できるような良い構造であったということだと思います。それゆえ回答に書いた「構造的問題」という表現は変でした。すみませんがが「制御上の問題」に訂正させていただきました。
guest

0

tkinter詳しくないのですが、.update_idletasks(Widgetのメンバのようなので、以下のようにwait(canvasを渡せば動作します。

Python

1# 略 2#■待ち処理等 3def wait(canvas): 4 canvas.update_idletasks() 5 canvas.update() 6 time.sleep(0.2) # 誤字修正 7# 略 8while 1: 9 # 略 10 wait(canvas) 11 # 略

イメージ説明

投稿2018/12/03 14:11

can110

総合スコア38256

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

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

suugaku_nyumon

2018/12/03 14:42

前回の質問に引き続きまたありがとうございます。 canvasに直すと動いたのですが、アニメーションを止めた後 Traceback (most recent call last): File "2dcell.py", line 63, in <module> modifyCell(canvas,A,k,CID) File "2dcell.py", line 37, in modifyCell canvas.itemconfig(CID[i][j],fill=CL[A[k][i][j]]) File "C:\Python37\lib\tkinter\__init__.py", line 2578, in itemconfigure return self._configure(('itemconfigure', tagOrId), cnf, kw) File "C:\Python37\lib\tkinter\__init__.py", line 1476, in _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) _tkinter.TclError: invalid command name ".!canvas" と表示されますが、一体これは何が原因なのでしょうか?
can110

2018/12/03 14:53

出ますね。メッセージで検索すると、https://stackoverrun.com/ja/q/4362155が出てきます。 ざっと読んでみましたが、アニメーション処理のお行儀が悪いと発生するようです。 この対処方法(正しいアニメーションの仕方)は詳しくないので分かりません…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問