TclError:无效的命令名称“。!frame。!canvas”

时间:2019-09-15 20:15:43

标签: python python-3.x tkinter

我正在将Jupyter Notebook与python 3.7.1版一起使用,以使用tkinter软件包构建蛇游戏。好吧,这更像是从github复制其他人的代码,然后自己修改。目标是制作一个由系统玩10次的蛇游戏。因此,在完成第一个游戏后,tkinter框架将关闭,另一个将弹出并重复直到10次。问题在于,每次游戏结束并关闭框架时,系统都会发出警告,并且在进行5或6次迭代后,系统将强制停止并给出与警告相同的错误消息。

这是警告:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\user\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:\Users\user\Anaconda3\lib\tkinter\__init__.py", line 749, in callit
    func(*args)
  File "<ipython-input-18-b0768e06fac0>", line 132, in tick
    self.render()
  File "<ipython-input-18-b0768e06fac0>", line 95, in render
    self.canvas.delete(tkinter.ALL)
  File "C:\Users\user\Anaconda3\lib\tkinter\__init__.py", line 2514, in delete
    self.tk.call((self._w, 'delete') + args)
_tkinter.TclError: invalid command name ".!frame.!canvas"

这是使系统强制停止进程的错误消息:

TclError                                  Traceback (most recent call last)
<ipython-input-22-d3ce3af75353> in <module>
      1 bots = []
      2 for i in range(0, 10):
----> 3     bots.append(snake_bot((i + 1), 10))

<ipython-input-18-b0768e06fac0> in __init__(self, bot_id, speed)
     75         self.direction = random.choice(availabel_directions)
     76 
---> 77         self.start()
     78 
     79     def draw_rect(self, x, y, color='#00f'):

<ipython-input-18-b0768e06fac0> in start(self)
    134 
    135     def start(self):
--> 136         self.tick()
    137         self.window.mainloop()
    138 

<ipython-input-18-b0768e06fac0> in tick(self)
    130         self.move_snake(self.direction)
    131         self.check_food()
--> 132         self.render()
    133         self.window.after(int(1000 / self.speed), self.tick)
    134 

<ipython-input-18-b0768e06fac0> in render(self)
     93 
     94     def render(self):
---> 95         self.canvas.delete(tkinter.ALL)
     96 
     97         for x in range(0, self.X):

~\Anaconda3\lib\tkinter\__init__.py in delete(self, *args)
   2512     def delete(self, *args):
   2513         """Delete items identified by all tag or ids contained in ARGS."""
-> 2514         self.tk.call((self._w, 'delete') + args)
   2515     def dtag(self, *args):
   2516         """Delete tag or id given as last arguments in ARGS from items

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

这是我修改过的代码:

from tkinter import Tk, Canvas, Frame, BOTH
import tkinter
from collections import deque
from random import randint
import random
from IPython.display import clear_output

class snake_bot():
    def __init__(self, bot_id, speed):
        #
        self.bot_id = bot_id
        self.speed = speed

        self.X = 30
        self.Y = 20
        self.BLOCK_SIZE = 20

        self.window = Tk()
        self.window.geometry('{}x{}'.format(self.X * self.BLOCK_SIZE, self.Y * self.BLOCK_SIZE))
        self.window.resizable(False, False)

        self.frame = Frame(self.window)
        self.frame.master.title('Snake Bot - ID - ' +str(self.bot_id))
        self.frame.pack(fill=BOTH, expand=1)

        self.canvas = Canvas(self.frame)
        self.canvas.pack(fill=BOTH, expand=1)

        self.VALID_DIRECTIONS = {
            'Left': set(('Up', 'Down')),
            'Right': set(('Up', 'Down')),
            'Up': set(('Left', 'Right')),
            'Down': set(('Left', 'Right'))
        }

        self.MOVEMENTS = {
            'Left': lambda x, y: (x - 1, y),
            'Right': lambda x, y: (x + 1, y),
            'Up': lambda x, y: (x, y - 1),
            'Down': lambda x, y: (x, y + 1)
        }

        self.score = 0

        randX = randint(0, (self.X - 2))
        randY = randint(0, (self.Y - 2))
        coin_flip = randint(1, 2)
        if(coin_flip == 1):
            #X
            coin_flip = randint(1, 2)
            if(coin_flip == 1):
                #-
                self.snake = deque(((randX, randY), ((randX-1), randY))) 
            else:
                #+
                self.snake = deque(((randX, randY), ((randX+1), randY))) 
        else:
            #Y
            coin_flip = randint(1, 2)
            if(coin_flip == 1):
                #-
                self.snake = deque(((randX, randY), (randX, (randY-1)))) 
            else:
                #+
                self.snake = deque(((randX, randY), (randX, (randY+1)))) 

        in_s = True
        while(in_s == True):
            self.food = (randint(0, (self.X - 1)), randint(0, (self.Y - 1)))
            if self.food not in self.snake:
                in_s = False

        self.moves = deque()
        availabel_directions = ['Down', 'Up', 'Right', 'Left']
        self.direction = random.choice(availabel_directions)

        self.start()

    def draw_rect(self, x, y, color='#00f'):
        self.x1 = x * self.BLOCK_SIZE
        self.y1 = y * self.BLOCK_SIZE
        self.x2 = self.x1 + self.BLOCK_SIZE
        self.y2 = self.y1 + self.BLOCK_SIZE 
        return self.canvas.create_rectangle(self.x1, self.y1, self.x2, self.y2, fill=color)

    def draw_background(self, x, y):
        self.x1 = x * self.BLOCK_SIZE
        self.y1 = y * self.BLOCK_SIZE
        self.x2 = self.x1 + self.BLOCK_SIZE
        self.y2 = self.y1 + self.BLOCK_SIZE
        return self.canvas.create_rectangle(self.x1, self.y1, self.x2, self.y2, fill='white')

    def render(self):
        self.canvas.delete(tkinter.ALL)

        for x in range(0, self.X):
            for y in range(0, self.Y):
                self.draw_background(x, y)
        for self.x, self.y in self.snake:
            self.draw_rect(self.x, self.y, color='#00f')
        self.x, self.y = self.food
        self.draw_rect(self.x, self.y, color='#f00')

    def create_food(self):
        self.s = set(self.snake)
        while True:
            self.food = randint(0, self.X - 1), randint(0, self.Y - 1)
            if self.food not in self.s:
                return self.food

    def check_food(self):
        self.s = set(self.snake)
        if self.food in self.s:
            self.increase_score()
            self.food = self.create_food()
        else:
            self.snake.popleft()

    def random_direction(self):
        self._direction = self.moves[-1] if self.moves else self.direction 
        availabel_directions = ['Down', 'Up', 'Right', 'Left']
        self.key = random.choice(availabel_directions)
        if self.key in self.VALID_DIRECTIONS[self._direction]:
            self.moves.append(self.key)

    def tick(self):
        self.random_direction()
        self.direction = self.moves.popleft() if self.moves else self.direction
        self.move_snake(self.direction)
        self.check_food()
        self.render()
        self.window.after(int(1000 / self.speed), self.tick)

    def start(self):
        self.tick()
        self.window.mainloop()

    def increase_score(self):
        self.score += 1
        if not self.score % 5:
            # increase speed after the snake eats 5 times
            self.speed += 2
        clear_output()
        print('ID - ', self.bot_id, 'score:', self.score, 'speed:', self.speed)

    def move_snake(self, direction):
        self.x, self.y = self.snake[-1]
        self.next_point = self.MOVEMENTS[self.direction](self.x, self.y)

        self.s = set(self.snake)
        if self.next_point in self.s:
            self.window.destroy()
            clear_output()
            print('You just ate yourself')
            print('ID - ', self.bot_id, 'score:', self.score, 'speed:', self.speed)
        if self.x < 0 or self.x >= self.X or self.y < 0 or self.y >= self.Y:
            self.window.destroy()
            clear_output()
            print('You crashed into a wall')
            print('ID - ', self.bot_id, 'score:', self.score, 'speed:', self.speed)

        self.snake.append(self.next_point)

bots = []
for i in range(0, 10):
    bots.append(snake_bot((i + 1), 10))

我试图找到解决方案,但直到现在我仍然被困住。我希望有人可以帮助我找到解决该问题的方法。提前谢谢你

1 个答案:

答案 0 :(得分:0)

我认为问题在于您无法真正控制self.windows和

self.canvas存在。

我做了两个更改,现在脚本显然可以工作了。。。显然是!!

SELECT SUM(trans_value) total, bectrn_id, becat_id
  FROM brvo_bemrc_transactions
 WHERE year = p_year
   AND trn_type = p_trntype
   AND doc_type = p_doctype
   AND company = p_company
   AND bedfn_id = p_bedfn_id
   AND bectrn_id = v_bectrn_id
   AND becat_id = v_becat_id
   AND extract(year from last_update_date) = p_year - 1
   AND mod(to_number(to_char(last_update_date, 'q')), 4) + 1 = to_number(to_char(sysdate, 'q'))
 GROUP BY bectrn_id, becat_id
 ORDER BY bectrn_id, becat_id;

在这里

def render(self):

    try:
        self.canvas.delete(tkinter.ALL)

        for x in range(0, self.X):
            for y in range(0, self.Y):
                self.draw_background(x, y)
        for self.x, self.y in self.snake:
            self.draw_rect(self.x, self.y, color='#00f')
        self.x, self.y = self.food
        self.draw_rect(self.x, self.y, color='#f00')
    except:
        pass

我明白了

你只是吃了饭

ID-1分:0速度:10

你只是吃了饭

ID-2分:0速度:10

你撞到墙上

ID-3分:0速度:10

你撞到墙上

ID-4分:1速度:10

你撞到墙上

ID-5分:0速度:10

你撞到墙上

ID-6得分:0速度:10

你撞到墙上

ID-7分:0速度:10

你撞到墙上

ID-8分:1速度:10

你只是吃了饭

ID-9得分:0速度:10

你撞到墙上

ID-10分:0速度:10