当我启动程序时,似乎没有任何问题。只有当我关闭程序时,我才得到错误信息。
_tkinter.TclError: invalid command name ".!canvas"
当我运行我的程序时,我的按钮也没有影响。我注释了导致我出错的那行代码。对不起,代码太长了,但错误是在draw_letters()函数中。我不知道这个错误可能是什么。
编辑:把mainwindow.mainloop()放在程序的最后并没有帮助,它只是给我一个不同的错误。这是因为我的程序需要在更新画布之前等待用户输入。
import random
import tkinter as tk
from tkinter import font
# I'm using this import to create a command with a parameter for my buttons
from functools import partial
class EventListener(object):
def __init__(self, current_letter):
self.current_letter = current_letter
def key_input(self, char):
self.current_letter = char
def get_current_letter(self):
return self.current_letter
def get_random_word():
word_list = []
with open('words.txt', 'r') as word_file:
for word in word_file:
if 4 < len(word) < 14:
word_list.append(word.strip('\n'))
return word_list[random.randint(0, len(word_list) - 1)]
def draw_gallows():
canvas.create_line(60, 350, 300, 350, width=2)
canvas.create_line(105, 350, 105, 20, width=2)
canvas.create_line(105, 20, 240, 20, width=2)
canvas.create_line(240, 20, 240, 50, width=2)
canvas.create_line(105, 85, 170, 20, width=2)
canvas.create_line(105, 95, 180, 20, width=2)
def draw_body_part(mistakes):
if mistakes <= 1:
canvas.create_oval(209, 50, 269, 110, width=2)
elif mistakes <= 2:
canvas.create_line(240, 110, 240, 260, width=2)
elif mistakes <= 3:
canvas.create_line(240, 180, 190, 120, width=2)
elif mistakes <= 4:
canvas.create_line(240, 180, 290, 120, width=2)
elif mistakes <= 5:
canvas.create_line(240, 260, 200, 330, width=2)
elif mistakes <= 6:
canvas.create_line(240, 260, 280, 330, width=2)
def draw_dashes(word, x):
for i in word:
canvas.create_line(x, 260, x + 25, 260)
x += 36
def draw_letters(letters, x):
for letter in letters:
canvas.create_text(x, 260, letter) # this is the line that is erring #####################
x += 36
# TODO: Set up end condition window
def end_condition(hasWon):
pass
def play_one_round():
word = get_random_word()
print(word)
correct_guesses = []
mistakes = 0
x = (700 // len(word)) + 260
draw_dashes(word, x)
main_window.mainloop()
while (len(correct_guesses) != len(word)) or (mistakes == 6):
guess = button_clicked.current_letter
print(guess)
if guess in word:
correct_guesses.append(guess)
draw_letters(correct_guesses, x)
elif guess not in word:
mistakes += 1
draw_body_part(mistakes)
if mistakes == 6:
end_condition(hasWon=False)
else:
end_condition(hasWon=True)
# creating the window, canvas and buttons
main_window = tk.Tk()
main_window.title('Hangman')
main_window.geometry('800x580+240+30')
main_window.resizable(False, False)
canvas = tk.Canvas(main_window, background='white', width=800, height=360)
canvas.grid(row=0, column=0)
keyboard_panel = tk.Frame(main_window)
keyboard_panel.grid(row=1, column=0)
helv17 = font.Font(family='Helvetica', size=17, weight='bold')
helv12 = font.Font(family='Helvetica', size=12)
button_clicked = EventListener('')
for i in range(ord('a'), ord('z') + 1):
if i < ord('j'):
column = ord('a')
row = 0
elif i < ord('s'):
column = ord('j')
row = 1
else:
column = ord('s')
row = 2
# the partial keyword allows you to have a command with a parameter
button = tk.Button(keyboard_panel, text=chr(i), font=helv17,
command=partial(button_clicked.key_input, chr(i)), width=4)
button.grid(row=row, column=i - column, padx=10, pady=10)
new_game_button = tk.Button(keyboard_panel, text='New Game', font=helv12)
new_game_button.grid(row=2, column=8)
draw_gallows()
play_one_round()
我自己想明白了。问题是,播放一轮是通过一个while循环,尽管它不应该。为了解决我的问题,我不得不完全删除play_one_round函数,并将该函数中的所有逻辑放到key_input函数中(与按钮命令相同),我还不得不删除while循环。改完之后,把mainloop放在程序的最后才是合理的。我现在已经完成了程序,没有任何错误。我现在唯一要改的就是end_condition窗口。如果谁有类似的错误,希望你能从我的努力中学习。想玩免费挂机游戏的朋友,请欣赏。
import random
import tkinter as tk
from tkinter import font
# Import to create a command with a parameter for buttons
from functools import partial
def get_random_word():
word_list = []
with open('words.txt', 'r') as word_file:
for txt_word in word_file:
if 4 < len(txt_word) < 14:
word_list.append(txt_word.strip('\n'))
return word_list[random.randint(0, len(word_list) - 1)]
def draw_gallows():
canvas.create_line(60, 350, 300, 350, width=2)
canvas.create_line(105, 350, 105, 20, width=2)
canvas.create_line(105, 20, 240, 20, width=2)
canvas.create_line(240, 20, 240, 50, width=2)
canvas.create_line(105, 85, 170, 20, width=2)
canvas.create_line(105, 95, 180, 20, width=2)
def draw_body_part(mistakes):
if mistakes <= 1:
canvas.create_oval(209, 50, 269, 110, width=2)
elif mistakes <= 2:
canvas.create_line(240, 110, 240, 260, width=2)
elif mistakes <= 3:
canvas.create_line(240, 180, 190, 120, width=2)
elif mistakes <= 4:
canvas.create_line(240, 180, 290, 120, width=2)
elif mistakes <= 5:
canvas.create_line(240, 260, 200, 330, width=2)
elif mistakes <= 6:
canvas.create_line(240, 260, 280, 330, width=2)
def draw_dashes(word, x):
for i in word:
canvas.create_line(x, 260, x + 25, 260)
x += 36
def draw_letters(word, letter, x):
helv20 = font.Font(family='Helvetica', size=20, weight='bold')
for l in word:
if letter == l:
canvas.create_text(x + 10, 249, text=letter, font=helv20)
x += 36
def end_condition(has_won):
def new_game_button_command():
end_window.destroy()
new_game()
end_window = tk.Tk()
end_window.geometry('250x180+400+200')
end_window.title('Game Over!')
end_message_frame = tk.Frame(end_window)
end_message_frame.grid(row=0, column=0)
end_button_frame = tk.Frame(end_window)
end_button_frame.grid(row=1, column=0)
new_game_button = tk.Button(end_button_frame, text='Play new game',
command=new_game_button_command)
new_game_button.grid(row=0, column=0)
if has_won:
end_message = tk.Label(end_message_frame, text='Congratulations!! You won!!!', )
else:
end_message = tk.Label(end_message_frame, text=f'You Lost! The word was "{word}"')
end_message.pack()
end_window.mainloop()
def new_game():
global word
global correct_guesses
global mistakes
global x
global total_guesses
global canvas
canvas.destroy()
canvas = tk.Canvas(main_window, background='white', width=800, height=360)
canvas.grid(row=0, column=0)
draw_gallows()
word = get_random_word()
correct_guesses = []
mistakes = 0
total_guesses = []
x = (700 // len(word)) + 260
draw_dashes(word, x)
def key_input(char):
global word
global correct_guesses
global mistakes
global x
global total_guesses
guess = char
if guess not in total_guesses:
for letter in word:
if guess == letter:
correct_guesses.append(guess)
draw_letters(word, guess, x)
if guess not in word:
mistakes += 1
draw_body_part(mistakes)
total_guesses.append(guess)
if mistakes == 6:
end_condition(has_won=False)
elif len(correct_guesses) == len(word):
end_condition(has_won=True)
# creating the window, canvas and buttons
main_window = tk.Tk()
main_window.title('Hangman')
main_window.geometry('800x580+240+30')
main_window.resizable(False, False)
canvas = tk.Canvas(main_window, background='white', width=800, height=360)
canvas.grid(row=0, column=0)
keyboard_panel = tk.Frame(main_window)
keyboard_panel.grid(row=1, column=0)
helv17 = font.Font(family='Helvetica', size=17, weight='bold')
helv12 = font.Font(family='Helvetica', size=12)
for i in range(ord('a'), ord('z') + 1):
if i < ord('j'):
column = ord('a')
row = 0
elif i < ord('s'):
column = ord('j')
row = 1
else:
column = ord('s')
row = 2
# the partial keyword allows you to have a command with a parameter
button = tk.Button(keyboard_panel, text=chr(i), font=helv17,
command=partial(key_input, chr(i)), width=4)
button.grid(row=row, column=i - column, padx=10, pady=10)
reset_button = tk.Button(keyboard_panel, text='New Game', font=helv12, command=new_game)
reset_button.grid(row=2, column=8)
draw_gallows()
word = get_random_word()
correct_guesses = []
mistakes = 0
total_guesses = []
x = (700 // len(word)) + 260
draw_dashes(word, x)
main_window.mainloop()