【问题标题】:i get this error when I am running my hangman game in python: _tkinter.TclError: invalid command name ".!canvas"当我在 python 中运行我的刽子手游戏时出现此错误:_tkinter.TclError: invalid command name ".!canvas"
【发布时间】:2020-05-15 21:14:03
【问题描述】:

当我启动程序时,似乎没有任何问题。只有当我关闭程序时才会收到错误消息:

_tkinter.TclError: 无效的命令名称“.!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()

【问题讨论】:

    标签: python python-3.x tkinter tkinter-canvas


    【解决方案1】:

    我自己想出来的。问题是播放一轮正在经历一个while循环,即使它不应该。为了解决我的问题,我必须完全删除 play_one_round 函数并将该函数中的所有逻辑放入 key_input 函数(与按钮命令相同),我还必须删除 while 循环。更改后,将主循环放在程序末尾是有意义的。我现在已经完成了程序,没有任何错误。我现在唯一要更改的是 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-19
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多