Я получаю сообщение об ошибке _tkinter.TclError: неверное имя пути окна ".! Button" при уничтожении кнопки - PullRequest
1 голос
/ 25 апреля 2020
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()

Это мой код. Я получаю ошибку _tkinter.TclError: bad window path name ".!button" только при использовании метода уничтожения. Но я хочу удалить предыдущую кнопку, когда появляется другая кнопка. Что мне делать?

Ответы [ 2 ]

2 голосов
/ 25 апреля 2020

Что ты делаешь? Когда вы нажимаете кнопку «Click me» (и вызываете метод self.undo, где кнопка self.b1 уничтожена), а затем нажимаете кнопку «Again» (и вызываете метод 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 ; классы должны быть названы в CamelCase .

2) Вы должны наследовать классы вашего приложения Tkinter либо от Tk (использование показано ниже) Toplevel (то же самое, что и Tk, но использование ТОЛЬКО для потомков windows), класс Frame (почти такой же, как для Tk, но вам нужно упаковать / сетку / поместить этот Frame в окно).

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()
0 голосов
/ 25 апреля 2020

После того, как вы уничтожили кнопку b1 в функции undo(self), tkinter больше не может получить к ней доступ и будет сбит с толку, когда вы попытаетесь разместить где-нибудь в функции click(self).
Чтобы кнопка b1 исчезла только визуально, вы можете поместить это за пределами окна вместо того, чтобы уничтожать его.
Для этого замените

self.b1.destroy()

на

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

Это переместит кнопку b1 далеко влево, где она не может быть видимым.
При вызове функции click(self) кнопка появится снова, потому что она снова будет перемещена в окно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...