Невозможно удалить виджет после активации флажка в Python Tkinter

Я работаю над своим пет-проектом. При работе над графическим интерфейсом я столкнулся с проблемой. Я хочу добавить новый виджет после первого нажатия на флажок, а при втором нажатии этот виджет должен быть удален. Но на самом деле у меня с этим проблема. Мой новый виджет был добавлен, но не удален. Не могли бы вы найти решение этой проблемы?

Это моя минимальная воспроизводимая часть кода. Класс Window при инициализации создает объект TK как переменную self.root и создает для него флажок cb. Этот флажок имеет команду self.create_or_delete_new_field, которая зависит от статуса cb_var, который является переменной флажка. Если cb_var имеет значение True, на self.root создается новый лабек lbl, если False — удаляется.

import tkinter as tk

class Window:

    def __init__(self):
        # pre-setups window
        self.root = tk.Tk()
        # checkbox
        cb_var = tk.BooleanVar()
        cb_var.set(0)
        cb = tk.Checkbutton(self.root, text = "Checkbox1", onvalue=True, offvalue=False, variable=cb_var,
                             command=lambda: self.create_or_delete_new_field(cb_var))
        cb.grid(row=0, column=0)

        self.root.mainloop()

    def create_or_delete_new_field(self, cb_var: bool):
        lbl = tk.Label(self.root, text=f" Created Label")
        if cb_var.get():
            lbl.grid(row=0, column=1, sticky='w')
        else:
            lbl.grid_remove()

app = Window()

Я пробовал не только метод Grid_remove(), но и Grid_forget(), Destroy(). Как я вижу, корень проблемы глубже, чем эти методы, но мой опыт не может этого обнаружить.

Каждый раз, когда вы звоните create_or_delete_new_field(), вы создаете совершенно новую метку, а затем либо делаете ее видимой, либо оставляете невидимой. Вы НИКОГДА ничего не делаете с предыдущей меткой, потому что это значение lbl исчезло, как только функция завершилась. Вам нужно, чтобы lbl было чем-то постоянным — атрибутом вашего класса или глобальной переменной.

jasonharper 13.06.2024 15:16
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот рабочий пример. Идея состоит в том, чтобы создать экземпляр Label во время Window.__init__(), чтобы вы создавали только одну метку. Я также использовал Window в качестве root, наследуя от tk.Tk, поскольку это обычная практика. Другой трюк заключается в правильном использовании self, чтобы метод toggle_widget имел доступ как к cb_var, так и к lbl.

import tkinter as tk


class Window(tk.Tk):
    def __init__(self) -> None:
        super().__init__()
        self.geometry('400x400')
        self.title('Window')

        self.cb_var = tk.BooleanVar(self, False)  # you can set the initial value here
        # NOTE: specifying on/off values isn't strictly necessary
        self.cb = tk.Checkbutton(
            self,
            text='Checkbox1',
            variable=self.cb_var,
            command=self.toggle_widget,
        )
        self.cb.grid(row=0, column=0)

        self.lbl = tk.Label(self, text='Hello!')

    def toggle_widget(self) -> None:
        if self.cb_var.get():
            self.lbl.grid(row=0, column=1, sticky='w')
        else:
            self.lbl.grid_forget()


if __name__ == '__main__':
    app = Window()
    app.mainloop()

спасибо большое, ваш пример очень полезен!

vldrud 13.06.2024 16:18

Рад, что смог помочь. Если этот ответ вам помог, отметьте его как «принятый» с помощью кнопки с галочкой, чтобы другие знали, что на этот вопрос уже дан ответ.

JRiggles 13.06.2024 16:48

Объяснение в виде комментариев

import tkinter as tk

class Window(tk.Tk): #make root as argument

    def __init__(self):
        
        #Add this line
        super().__init__()
        self.geometry('200x100')
        self.title('Window')
        
        # No need of declaring boolen_variable as we create 2 functions
        # Declare self.lbl here and don't pack (or don't add grid)
        #There is no need of using f-string
        self.lbl = tk.Label(self, text= "Created Label")         
               
        self.cb = tk.Checkbutton(self, text = "Create Label", command=self.create_lbl)
        self.cb.grid(row=0, column=0)
        

    def create_lbl(self):
        
        # pack the lbl here
        self.lbl.grid(row=1, column=0, sticky='w')
        
        # Change the text of check button as 'Hide label'           
        self.cb.configure(text = 'Hide_Label', command = self.hide_lbl)
        
    def hide_lbl(self):
    
        # Use grid_forget to hide label
        self.lbl.grid_forget()
        
        # Change the text of check button as 'Create label'
        self.cb.configure(text = 'Create Label', command = self.create_lbl)
        
        
if __name__ == '__main__':
    app = Window()
    app.mainloop()   

Другие вопросы по теме

Похожие вопросы

Как в Confluence воспроизвести ручной поиск с помощью поиска API?
Надежный способ проверить, был ли метод обернут декоратором изнутри
Как проверить, не может ли пользователь отправлять сообщения (был ограничен или отключен звук) в чате Telegram с помощью Telethon API?
Как сохранить векторы, созданные AzureOpenAIEmbeddingSkill, в индексаторе с учетом моей текущей настройки
Каков наиболее эффективный способ заполнения нескольких столбцов значениями из других столбцов таким образом, чтобы их можно было соединить с суффиксом?
Разбиение на страницы данных из DynamoDB при использовании FilterExpression и Limit
Get_swagger_ui_html вызывает отображение нежелательных параметров сервера в приложении FastAPI
Есть ли что-то вроде указателя для массивов numpy?
SQLAlchemy: проверка того, установлен ли фильтр, вызывает `TypeError: логическое значение этого предложения не определено`
Как отправлять структурированные журналы в стек ELK с настраиваемыми полями с помощью ведения журнала Python?