【问题标题】:I get the error _tkinter.TclError: bad window path name ".!button" when I destroy the button我在销毁按钮时收到错误 _tkinter.TclError: bad window path name ".!button"
【发布时间】:2020-08-09 07:54:48
【问题描述】:
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()

这是我的代码。只有当我使用 destroy 方法时,我才会收到 _tkinter.TclError: bad window path name ".!button" 错误。但是当另一个按钮出现时,我想删除上一个按钮。我该怎么办?

【问题讨论】:

  • 你可能想要.place_forget() 而不是.destroy()..
  • 您正在放置已销毁的按钮 (self.b1)。

标签: python class oop object tkinter


【解决方案1】:

你在做什么?当您单击“单击我”按钮(并调用 self.undo 方法,其中 self.b1 按钮被销毁)然后单击“再次”按钮(并调用 self.click 方法,该方法试图将已销毁的self.b1 按钮),您会收到错误消息,即该按钮不存在。当然不是因为你毁了它。

您似乎打算隐藏该按钮。如果您打算这样做,那么您可以只使用 .place_forget() 方法(还有分别用于包和网格窗口管理器的 .pack_forget().grid_forget() 方法)隐藏小部件,但不会破坏它,因此您可以在需要时再次恢复它。

这是你的固定代码:

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()

我还可以给你一些关于实施的建议:

1) 你应该按照PEP8 style写代码;类应以CamelCase 命名。

2) 您应该从 Tk 继承您的 Tkinter 应用程序类(用法如下所示) Toplevel(与 Tk 相同,但仅用于子窗口),Frame 类(与 Tk 几乎相同,但您需要将该框架打包/网格/放置在窗口中)。

3) 最好在单独的函数中创建小部件(这有助于开发复杂的大型应用程序)。

4) 建议在创建窗口前写if __name__ == "__main__":条件(这样的话,你可以从其他模块导入这段代码,这样窗口就打不开了)。

这是一个例子:

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()

【讨论】:

    【解决方案2】:

    在您销毁 undo(self) 函数中的按钮 b1 后,tkinter 无法再访问它,并且当您尝试将其放置在 click(self) 函数中的某个位置时会感到困惑。
    要使按钮 b1 仅在视觉上消失,您可以将其放置在窗口之外而不是销毁它。
    这样做替换

    self.b1.destroy()
    

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

    这会将按钮 b1 移到最左边,看不到它。
    调用click(self)函数时,按钮会重新出现,因为它会再次移动到窗口内。

    【讨论】:

    • 这会将按钮 b1 移到最左边,看不到它 -- 千万不要那样做。有.place_forget() 方法。所以你需要做self.b1.place_forget() 而不是self.b1.place(...)
    猜你喜欢
    • 2018-09-24
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2013-10-23
    相关资源
    最近更新 更多