【问题标题】:window destruction error in TkinterTkinter 中的窗口破坏错误
【发布时间】:2018-04-07 21:40:56
【问题描述】:

我正在尝试使用 Tkinter 创建一个 Hangman 游戏 GUI。除了几件事之外,我还有完整的工作代码。我想创建一个循环,通过按按钮重新启动游戏或按“否”退出游戏。

我还希望这些按钮出现在新窗口中并在之前关闭窗口。

我已经删除了代码中不需要的部分,因此您只会看到主要问题区域和主要思想。要使其工作,您只需输入“b”,然后输入“o”:

from Tkinter import *
item = "BOO"
oldString = "-" * (len(item))
blank = "-" * (len(item))
guesses = 10

def start():
    winMain.destroy()
    mainMenu()


def theWinner():
    def end():
        root.destroy()

    def replay():
        root.destroy()
        mainMenu()

    root = Tk()
    root.title("HANGMAN GAME DEMO")
    answer = Entry(root)
    answer.insert(END, "You Won!!! Play again?")
    answer.grid(row = 0, column = 0)
    yesB=Button(root, text = "Yes", command = replay)
    yesB.grid(row = 1, column = 0)
    noB = Button(root, text = "Quit", command = end)
    noB.grid(row = 1, column = 1)
    root.mainloop()


def mainMenu():
    def gameOn():
        global guesses
        global oldString
        newString = ""
        i = 0
        x = len(item)
        hanged = ""
        readString = answerIn.get().upper()
        winner = 1
        if readString not in item:
            guesses -= 1
        elif readString in item:
            while x > 0:
                if item[i] != readString:
                    newString = newString + oldString[i]
                elif item[i] == readString:
                    newString = newString + readString
                i +=1   
                x -=1

            oldString = newString
            out.config(state=NORMAL)
            out.delete(0,END)
            out.insert(0,oldString);
            out.config(state=DISABLED)
            answerIn.delete(0,END)
            if oldString == item:
                win.destroy()
                theWinner()


        newString = ""
        i=0
        x=len(item)

        answerIn.delete(0,END)

    win = Tk()
    win.geometry ("665x480")
    win.title("HANGMAN GAME DEMO")
    win.configure(background='LightBlue2')

   #Display of the word user is trying to guess
    guessWord = Entry(win, disabledbackground = "mint cream", disabledforeground = "black", font="helvetica 11 bold", width = 12, border = 2)
    guessWord.grid(row=1, column=0, pady = 10, padx = 6, sticky = W)
    guessWord.insert(END, "The word is: ")
    guessWord.config(state = DISABLED)
    #guessWord = Label(win, bg = "mint cream", font="helvetica 10 ", text = "The word you have to guess is: ")
    guessWord.grid(row=1, column=0, pady = 10, padx = 9, sticky = W)
    out = Entry(win, border = 2,  font="helvetica 15 bold", width = 12, disabledforeground = "black", disabledbackground = "gold")
    out.insert(0,blank);
    out.config(state=DISABLED)
    out.grid(row=1, column=0, pady = 10, padx = 200, sticky = W)


    #Type in Window
    answer = Entry(win, disabledbackground = "mint cream", disabledforeground = "black", font="helvetica 10", width = 21, border = 2)
    answer.grid(row=2, column=0, pady = 10, padx = 8, sticky = W)
    answer.insert(END,"Please type in the letter: ")
    answer.config(state=DISABLED)
    answerIn = Entry(win,width = 3, border = 2)
    answerIn.focus_set()
    answerIn.grid(row=2, column=0, pady = 10, padx = 200, sticky = W)

    b = Button(win, text = "Enter",command = gameOn, bg = "chartreuse2", font="helvetica 10 bold",)
    b.grid(row=2, column=0, pady = 10, padx = 200)


    win.mainloop()

winMain = Tk()
winMain.title("HANGMAN GAME DEMO")
imageLabel = Label(winMain, text = "HELLO!")
imageLabel.pack()
winMain.after(1000, start)
winMain.mainloop()

如果我按“否”,我会收到以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1541, in __call__
    return self.func(*args)
  File "C:/Python27/8.py", line 69, in gameOn
    answerIn.delete(0,END)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 2509, in delete
    self.tk.call(self._w, 'delete', first, last)
TclError: invalid command name ".94412392"

如果我按“是”,它似乎不会从头开始重新启动游戏。它只允许我输入一个字符,然后再次打开 Win 窗口。

我哪里出错了,有没有快速解决方法?

【问题讨论】:

  • 退出的时候报错没问题,销毁的时候报错。

标签: python loops tkinter window exit


【解决方案1】:

这个错误是因为在销毁窗口后你想删除entry widget中的内容。看这部分

def mainMenu():
    .......
    .......
    ......
    if oldString == item:
           win.destroy()
           theWinner()


   # newString = ""
   # i=0
   # x=len(item)

 #   answerIn.delete(0,END)

您可以看到我在关闭窗口后评论了您不需要它的部分,当您这样做时,错误不会再次弹出。关于游戏未启动的事情,您应该使用相同的命令创建另一个函数因为它

def replay():
    root.destroy()
    mainMenu()

当你调用它时它不起作用。我还建议你使用Toplevel窗口而不是调用Tkmainloop多个。

查看此链接[Toplevel documentation][1]。每个人都很难调试您的代码,因为您在另一个函数下创建了多个函数,将它们分开。

【讨论】:

  • 我确实分别拥有所有功能,但它无法识别命令。当我尝试 root.destroy() 没有函数内部的函数时,它一直声称这个变量不存在。
  • 作为全局变量使用
【解决方案2】:

你需要在结束游戏时重置oldString

替换

if oldString == item:
    win.destroy()
    theWinner()

if oldString == item:
    win.destroy()
    oldString='---'
    theWinner()

它应该可以工作(我已经测试过)。

【讨论】:

    【解决方案3】:

    在不尝试解决代码库上的问题的情况下,我建议您将代码切换为基于类的代码,这样您就可以更好地控制并且可以更轻松地保留使某些 gui-stuff 按预期工作所需的引用.额外的好处是您也可以放弃 globals

    有一个优秀的 py2 tkinter doc 从中复制了这个最小示例,只是为了让您了解基于类的 gui 编码风格,这通常是首选的方式。您似乎使用的是 py2,但是如果您使用的是 py3,则文档也可以正常工作,您只需要跟踪导入中的细微差别。

    import Tkinter as tk
    class Application(tk.Frame):
        def __init__(self, master=None):
            tk.Frame.__init__(self, master)
            self.grid()
            self.createWidgets()
    
        def createWidgets(self):
            self.quitButton = tk.Button(self, text='Quit', command=self.quit)
            self.quitButton.grid()
    
    app = Application()
    app.master.title('Sample application')
    app.mainloop() 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-15
      • 2019-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      相关资源
      最近更新 更多