首先,我对使用 Tkinter 非常陌生,
我遇到的问题是,如果我只有一种对象类型,我的代码就可以工作。如果它是该标签类型中唯一的一种,它将正确交互。因此,如果每次执行时我都有一艘“船”和 100 个“炮弹”,它就会正确执行。
该代码检测两个对象之间是否存在碰撞,然后将当前选定项目的颜色更改为随机颜色。因此,只要当前只有一种标签类型,它就可以正常工作。因此,如果我单击并将“船”拖到“外壳”中,它将切换它的颜色。然后,如果我取 100 个外壳中的 1 个并做同样的事情,我会收到此错误。
我不明白为什么当只有一个给定类型的对象并且与无限数量的其他对象交互时它可以正常工作,但是当有多个标签类型时它会失败。
它正确选择了所选对象的 ID 号,所以我现在迷路了,感谢任何帮助。
以下是我收到的错误和我正在使用的代码。它只是执行所需任务所需的重要部分。碰撞代码与代码中的相同。
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1487, in __call__
return self.func(*args)
File "H:/Charles Engen/PycharmProjects/Battleship/BattleShipGUI.py", line 112, in on_token_motion
self.collision_detection(event)
File "H:/Charles Engen/PycharmProjects/Battleship/BattleShipGUI.py", line 85, in collision_detection
self.canvas.itemconfig(current_token, outline=_random_color())
File "C:\Python34\lib\tkinter\__init__.py", line 2385, in itemconfigure
return self._configure(('itemconfigure', tagOrId), cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 1259, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: unknown option "22"
import tkinter as tk
from random import randint
HEIGHT = 400
WIDTH = 680
def _random_color():
'''Creates a random color sequence when called'''
random_color = ("#"+("%06x" % randint(0, 16777215)))
return random_color
class Board(tk.Tk):
'''Creates a Board Class'''
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.menu_item = tk.Menu(self)
self.file_menu = tk.Menu(self.menu_item, tearoff=0)
self.file_menu.add_command(label='New', command=self.new_game)
self.file_menu.add_command(label='Exit', command=self.quit)
self.config(menu=self.file_menu)
self.canvas = tk.Canvas(width=WIDTH, height=HEIGHT)
self.canvas.pack(fill='both', expand=True)
# adds variable that keeps track of location
self._token_location_data = {"x": 0, "y": 0, "item": None}
def _create_object(self, coord, fcolor, color, token_name):
'''Creates an object with a tag, each object is assigned the ability to be clicked and dragged'''
(x, y) = coord
if token_name == 'boat':
points = [10+x, 10+y, 20+x, 20+y, 110+x, 20+y, 120+x, 10+y, 80+x,
10+y, 80+x, 0+y, 60+x, 0+y, 60+x, 10+y]
self.canvas.create_polygon(points, outline=fcolor, fill=color, width=3, tag=token_name)
elif token_name == 'shell':
self.canvas.create_oval(0+x, 0+y, 10+x, 10+y, outline=fcolor, fill=color, width=3, tag=token_name)
self.canvas.tag_bind(token_name, '<ButtonPress-1>', self.on_token_button_press)
self.canvas.tag_bind(token_name, '<ButtonRelease-1>', self.on_token_button_press)
self.canvas.tag_bind(token_name, '<B1-Motion>', self.on_token_motion)
def collision_detection(self, event):
'''This function tracks any collision between the boat and shell objects'''
# I will upgrade this to take any object collision
token = self.canvas.gettags('current')[0]
current_token = self.canvas.find_withtag(token)
x1, y1, x2, y2 = self.canvas.bbox(token)
overlap = self.canvas.find_overlapping(x1, y1, x2, y2)
for item in current_token:
for over in overlap:
if over != item:
# Changes the color of the object that is colliding.
self.canvas.itemconfig(current_token, outline=_random_color())
# The following three functions are required to just move the tokens
def on_token_button_press(self, event):
'''Adds ability to pick up tokens'''
# Stores token item's location data
self._token_location_data['item'] = self.canvas.find_closest(event.x, event.y)[0]
self._token_location_data['x'] = event.x
self._token_location_data['y'] = event.y
def on_token_button_release(self, event):
'''Adds ability to drop token'''
# Resets the drag
self._token_location_data['item'] = self.canvas.find_closest(event.x, event.y)
self._token_location_data['x'] = event.x
self._token_location_data['y'] = event.y
def on_token_motion(self, event):
'''Adds ability to keep track of location of tokens as you drag them'''
# Computes how much the object has moved
delta_x = event.x - self._token_location_data['x']
delta_y = event.y - self._token_location_data['y']
# move the object the appropriate amount
self.canvas.move(self._token_location_data['item'], delta_x, delta_y)
# record the new position
self._token_location_data['x'] = event.x
self._token_location_data['y'] = event.y
# Detects collision between objects
self.collision_detection(event)
def new_game(self):
'''Creates new game by deleting the current canvas and creating new objects'''
# Deletes current canvas
self.canvas.delete('all')
# runs the create board mechanism
self._generate_board()
# adds code to create a shell and boat on the screen from the appropriate function
for i in range(1):
self._create_object((410, 15*i), _random_color(), _random_color(), 'boat')
for i in range(4):
for j in range(10):
self._create_object((590+(i*10), 15*j), _random_color(), _random_color(), 'shell')
def main():
app = Board()
app.mainloop()
if __name__ == '__main__':
main()