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

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

ただいまの
回答率

88.59%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,741

suugaku_nyumon

score 22

 質問内容

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'
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

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

_tkinter.TclError: invalid command name ".!canvas"
と表示されますが、一体これは何が原因なのでしょうか?

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

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

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

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

... 省略

#def wait(canvas):
#    ... この関数は使わない ...

... 省略

# ■実行メイン
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


def animate():
    global k
    modifyCell(canvas, A, k, CID)
    execCell(A, k, 1 - k, 5)
    # wait(canvas)  # 使わない
    k = 1 - k
    root.after(200, animate)  # 0.2秒経過したら再度この関数を起動する


root.after(200, animate)  # 初回のコールバック登録
root.mainloop()


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/04 01:33

    ありがとうございます。

    初めて遭遇するエラーで困っていたので助かりました。

    キャンセル

  • 2018/12/04 02:07

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

    キャンセル

0

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

# 略
#■待ち処理等
def wait(canvas):
    canvas.update_idletasks()
    canvas.update()
    time.sleep(0.2) # 誤字修正
# 略
while 1:
    # 略
    wait(canvas)
    # 略


イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/03 23: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"

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

    キャンセル

  • 2018/12/03 23:53

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

    キャンセル

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

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る