简体   繁体   English

我在销毁按钮时收到错误 _tkinter.TclError: bad window path name “.!button”

[英]I get the error _tkinter.TclError: bad window path name “.!button” when I destroy the button

from tkinter import *
master=Tk()
class check:
def __init__(self,root):
    self.root=root

    self.b1=Button(root,text="Click me",command=self.undo)
    self.b2=Button(root,text="Again",command=self.click)

def click(self):
    self.b1.place(relx=0.5,rely=0.5)

def undo(self):
    self.b1.destroy()
    self.b2.place(relx=0.2,rely=0.2)
c=check(master)
c.click() 
master.mainloop()

This is my code.这是我的代码。 I get _tkinter.TclError: bad window path name ".!button" error only when I use destroy method.只有当我使用销毁方法时,我才会收到_tkinter.TclError: bad window path name ".!button"错误。 But I want to delete previous button when another button appears.What should I do?但是当另一个按钮出现时,我想删除上一个按钮。我该怎么办?

What are you doing?你在做什么? When you click the "Click me" button (and call the self.undo method, where the self.b1 button is destroyed) and then click the "Again" button (and call the self.click method, which tries to place already destroyed self.b1 button), you get the error, that the button does not exist.当您单击“单击我”按钮(并调用self.undo方法,其中 self.b1 按钮被销毁)然后单击“再次”按钮(并调用self.click方法,该方法试图将已销毁的位置self.b1 按钮),您会收到错误消息,即该按钮不存在。 Of course, it doesn't because you have destroyed it.当然,不是因为你毁了它。

It looks like you meant to hide the button.看起来您打算隐藏按钮。 If you intended to do this, then you could just use .place_forget() method (there are also .pack_forget() and .grid_forget() methods for pack and grid window managers, respectively), that hides the widget, but not destroys it, and hence you would be able to restore it again when you need.如果您打算这样做,那么您可以只使用.place_forget()方法(还有.pack_forget().grid_forget()方法分别用于 pack 和 grid window 管理器),隐藏小部件,但不破坏它,因此您可以在需要时再次恢复它。

Here is your fixed code:这是您的固定代码:

from tkinter import *


master = Tk()

class check:
    def __init__(self, root):
        self.root = root

        self.b1 = Button(root, text="Click me", command=self.undo)
        self.b2 = Button(root, text="Again", command=self.click)

    def click(self):
        self.b2.place_forget()
        self.b1.place(relx=0.5, rely=0.5)

    def undo(self):
        self.b1.place_forget()
        self.b2.place(relx=0.2, rely=0.2)

c = check(master)
c.click() 
master.mainloop()

I can also give you a piece of advice about the implementation:我还可以给你一些关于实施的建议:

1) You should write the code according to the PEP8 style ; 1)你应该按照PEP8风格编写代码; classes should be named in the CamelCase .类应以CamelCase命名。

2) You should inherit your Tkinter app class(es) either from Tk (usage is shown below) Toplevel(the same as Tk, but use ONLY for child windows), Frame class (almost the same as for Tk, but you need to pack/grid/place that Frame in a window). 2)您应该从 Tk 继承您的 Tkinter 应用程序类(用法如下所示)顶层(与 Tk 相同,但仅用于子窗口),框架 class(几乎与 Tk 相同,但您需要打包/网格/将该框架放置在窗口中)。

3) It's better to create the widgets in a separate function (it helps while developing complex and big apps). 3) 最好在单独的 function 中创建小部件(这有助于开发复杂的大型应用程序)。

4) It's recommended to write if __name__ == "__main__": condition before creating the window (if you do like this, you will be able to import this code from other modules, and the window won't open in that case). 4) 建议在创建 window 之前编写if __name__ == "__main__":条件(如果这样做,您将能够从其他模块导入此代码,并且 window 在这种情况下不会打开)。

Here is an example:这是一个例子:

from tkinter import *


class Check(Tk):
    def __init__(self):
        super().__init__()

        self.create_widgets()
        self.click()

    def create_widgets(self):
        self.b1 = Button(self, text="Click me", command=self.undo)
        self.b2 = Button(self, text="Again", command=self.click)

    def click(self):
        self.b2.place_forget()
        self.b1.place(relx=0.5, rely=0.5)

    def undo(self):
        self.b1.place_forget()
        self.b2.place(relx=0.2, rely=0.2)

if __name__ == "__main__":
    Check().mainloop()

After you destroyed button b1 in the undo(self) function tkinter cannot access it anymore and will be confused when you try to place is somewhere in the click(self) function.undo(self) function tkinter 中销毁按钮 b1 后,您将无法再访问它,并且当您尝试将其放置在click(self) ZC1C425268E68385D1AB5074C17A94F1 中的某处时会感到困惑。
To make button b1 only disappear visually you could place it outside of the window instead of destroying it.要使按钮 b1 仅在视觉上消失,您可以将其放置在 window 之外,而不是破坏它。
To do so replace为此更换

self.b1.destroy()

with

self.b1.place(relx=-5, rely=0)

This will move the button b1 far to the left, where it cannot be seen.这会将按钮 b1 移到最左侧,无法看到它。
When calling the click(self) function, the button will reappear, because it will be moved inside the window again.当调用click(self) function 时,按钮会重新出现,因为它会再次移动到 window 内部。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 _tkinter.TclError:错误的窗口路径名“.!button2” - _tkinter.TclError: bad window path name ".!button2" 错误:_tkinter.TclError:错误的窗口路径名“.!button” - Errror: _tkinter.TclError: bad window path name ".!button" Python tkinter:错误 _tkinter.TclError:错误的窗口路径名“.!button2” - Python tkinter: error _tkinter.TclError: bad window path name ".!button2" _tkinter.TclError: bad window path name ".!toplevel" 使关闭按钮退出 windows 无报错 - _tkinter.TclError: bad window path name ".!toplevel" Make the close button to exit the windows without error _tkinter.TclError: 错误的窗口路径名 - _tkinter.TclError: bad window path name 当我尝试运行它时,Tkinter 给了我一个 _tkinter.TclError: bad event type or keysym "button" - Tkinter is giving me a _tkinter.TclError: bad event type or keysym "button" when i try to run it _tkinter.TclError:错误的 window 路径名“.!checkbutton” - _tkinter.TclError: bad window path name “.!checkbutton” 我正面临 tkinter 按钮样式“_tkinter.TclError: Invalid state name a”的问题 - I am facing issue with tkinter button style "_tkinter.TclError: Invalid state name a" tkinter wait_window()提高tkinter.TclError:错误的窗口路径名 - tkinter wait_window() raising tkinter.TclError: Bad window path name 当我在 python 中运行我的刽子手游戏时出现此错误:_tkinter.TclError:命令名称“.!canvas”无效 - i get this error when I am running my hangman game in python: _tkinter.TclError: invalid command name ".!canvas"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM