- Как удалить виджеты Tkinter из окна?
- 4 ответа
- Как скрыть, восстановить и удалить Tkinter виджеты
- Скрыть и восстановить виджеты Tkinter
- pack_forget() метод для сокрытия виджетов Tkinter Widgets
- grid_forget() Метод скрытия виджетов, если используется макет grid
- grid_remove() Метод скрытия виджетов цинтера, если используется grid макет
- # Удаление виджетов — delete widgets
- # Упражнения
- # Добавление/удаление виджетов — Add/delete widgets
- # Упражнения
- # Добавление/удаление нескольких виджетов
- # Упражнения
Как удалить виджеты Tkinter из окна?
У меня есть список виджетов Tkinter, которые я хочу изменить динамически. Как я могу полностью удалить виджеты из моего окна?
4 ответа
Вы можете вызвать pack_forget , чтобы удалить виджет (если вы используете pack , чтобы добавить это к окну). Пример:
from tkinter import * root = Tk() b = Button(root, text="Delete me", command=lambda: b.pack_forget()) b.pack() root.mainloop()
Если вы используете pack_forget , позже вы можете снова увидеть виджет, снова вызывающий pack . Если вы хотите окончательно удалить его, вызовите destroy в виджет (тогда вы не сможете его повторно добавить). Если вы используете метод grid , вы можете использовать grid_forget или grid_remove для скрытия виджета.
@TheBeardedBerry: учтите, что pack_forget не удаляет виджеты, а только удаляет их из поля зрения. Они по-прежнему будут существовать, что может привести к утечке памяти, если вы продолжите воссоздание виджетов, не разрушая их.
Если я pack_forget фрейма и затем удаляю его, удалит ли он также дочерние виджеты или я должен удалить их по отдельности?
Один из способов сделать это — получить список подчиненных из фрейма, который необходимо очистить, уничтожить или «спрятать» в соответствии с вашими потребностями. Чтобы получить четкую рамку, вы можете сделать это следующим образом:
from tkinter import * root = Tk() def clear(): list = root.grid_slaves() for l in list: l.destroy() Label(root,text='Hello World!').grid(row=0) Button(root,text='Clear',command=clear).grid(row=1) root.mainloop()
Вы должны вызвать grid_slaves() , pack_slaves() или slaves() в зависимости от метода, который вы использовали для добавления виджета в фрейм.
У меня было 5 кнопок в окне. Затем мне нужно было добавить 3 новые кнопки и удалить старые кнопки. Но 2 старые кнопки были на окне. При таком решении все 5 кнопок удаляются и добавляются только 3 новые кнопки. Я использую шаблон MVP для моего приложения.
Я обнаружил, что, когда виджет является частью функции, а grid_remove является частью другой функции, он не удаляет ярлык. В этом примере.
def somefunction(self): Label(self, text=" ").grid(row = 0, column = 0) self.text_ent = Entry(self) self.text_ent.grid(row = 1, column = 0) def someotherfunction(self): somefunction.text_ent.grid_remove()
. не существует допустимого способа удаления метки.
Единственное решение, которое я смог найти, — дать ярлыку имя и сделать его глобальным:
def somefunction(self): global label label = Label(self, text=" ") label.grid(row = 0, column = 0) self.text_ent = Entry(self) self.text_ent.grid(row = 1, column = 0) def someotherfunction(self): global label somefunction.text_ent.grid_remove() label.grid_remove()
Когда я столкнулся с этой проблемой, был задействован класс, одна функция была в классе, а другая нет, поэтому я не уверен, что строки global label действительно необходимы в приведенном выше.
Тот факт, что нет способа удалить первый созданный вами ярлык, не связан с тем, что вы создаете его в одной функции и удаляете его в другой, просто вы не удерживаете ссылку. Это не вещь tkinter, это вещь программирования — чтобы действовать на объект, у вас должна быть ссылка на объект. Во втором примере вам не нужно использовать глобальную переменную. Вместо этого назначьте его self же, как вы делаете виджет ввода.
Сегодня я изучаю простую и эффективную обработку событий click, используя библиотеку tkinter gui в python3, которую я хотел бы поделиться внутри этого потока.
from tkinter import * cnt = 0 def MsgClick(event): children = root.winfo_children() for child in children: # print("type of widget is : " + str(type(child))) if str(type(child)) == "": # print("Here Message widget will destroy") child.destroy() return def MsgMotion(event): print("Mouse position: (%s %s)" % (event.x, event.y)) return def ButtonClick(event): global cnt, msg cnt += 1 msg = Message(root, text="you just clicked the button. " + str(cnt) + ". time. ") msg.config(bg='lightgreen', font=('times', 24, 'italic')) msg.bind("", MsgClick) msg.bind("", MsgMotion) msg.pack() #print(type(msg)) tkinter.Message def ButtonDoubleClick(event): import sys; sys.exit() root = Tk() root.title("My First GUI App in Python") root.minsize(width=300, height=300) root.maxsize(width=400, height=350) button = Button( root, text="Click Me!", width=40, height=3 ) button.pack() button.bind("", ButtonClick) button.bind("", ButtonDoubleClick) root.mainloop()
Надеюсь, что это поможет кому-то.
Как скрыть, восстановить и удалить Tkinter виджеты
- Скрыть и восстановить виджеты Tkinter
- Удалить тикинтерные виджеты Нажмите кнопку
В данном уроке мы продемонстрируем, как скрыть, восстановить и удалить Tkinter виджеты, нажав на кнопку. В конце мы также покажем, как удалить или убить существующие Tkinter-виджеты.
Скрыть и восстановить виджеты Tkinter
pack_forget() метод для сокрытия виджетов Tkinter Widgets
В отличие от метода pack в виджетах Tkinter, мы могли скрыть виджеты Tkinter, вызвав метод pack_forget() для того, чтобы сделать виджеты невидимыми.
try: import Tkinter as tk except: import tkinter as tk class Test(): def __init__(self): self.root = tk.Tk() self.label=tk.Label(self.root, text = "Label") self.buttonForget = tk.Button(self.root, text = 'Click to hide Label', command=lambda: self.label.pack_forget()) self.buttonRecover = tk.Button(self.root, text = 'Click to show Label', command=lambda: self.label.pack()) self.buttonForget.pack() self.buttonRecover.pack() self.label.pack(side="bottom") self.root.mainloop() def quit(self): self.root.destroy() app = Test()
self.buttonForget = tk.Button(self.root, text = 'Click to hide Label', command=lambda: self.label.pack_forget())
pack_forget() привязывается к команде кнопки buttonForget .
После нажатия кнопки виджет метки будет скрыт, но сама метка все еще существует, но становится невидимой.
Нам нужно снова вызвать метод pack() для упаковки виджета, чтобы сделать его видимым, или другими словами, для его восстановления.
grid_forget() Метод скрытия виджетов, если используется макет grid
Если виджеты размещаются в менеджере компоновки grid , то следует использовать метод grid_forget() для того, чтобы сделать виджеты Tkinter невидимыми.
try: import Tkinter as tk except: import tkinter as tk class Test(): def __init__(self): self.root = tk.Tk() self.label=tk.Label(self.root, text = "Label") self.buttonForget = tk.Button(self.root, text = 'Click to hide Label', command=lambda: self.label.grid_forget()) self.buttonRecover = tk.Button(self.root, text = 'Click to show Label', command=lambda: self.label.grid()) self.buttonForget.grid(column=0, row=0, padx=10, pady=10) self.buttonRecover.grid(column=0, row=1, padx=10, pady=10) self.label.grid(column=0, row=2, padx=10, pady=10) self.root.mainloop() def quit(self): self.root.destroy() app = Test()
self.buttonForget = tk.Button(self.root, text = 'Click to hide Label', command=lambda: self.label.grid_forget())
Здесь мы связываем метод grid_forget с командой кнопки.
Вы можете заметить, что позиция метки не совпадает до того, как она будет скрыта после повторного вызова метода grid .
Если мы хотим восстановить исходную позицию метки, то метод grid_remove будет правильным вариантом.
grid_remove() Метод скрытия виджетов цинтера, если используется grid макет
grid_remove() скрывает виджет, но запоминает опции сетки, такие как колонка и ряд .
try: import Tkinter as tk except: import tkinter as tk class Test(): def __init__(self): self.root = tk.Tk() self.label=tk.Label(self.root, text = "Label") self.buttonForget = tk.Button(self.root, text = 'Click to hide Label', command=lambda: self.label.grid_remove()) self.buttonRecover = tk.Button(self.root, text = 'Click to show Label', command=lambda: self.label.grid()) self.buttonForget.grid(column=0, row=0, padx=10, pady=10) self.buttonRecover.grid(column=0, row=1, padx=10, pady=10) self.label.grid(column=0, row=2, padx=10, pady=20) self.root.mainloop() def quit(self): self.root.destroy() app = Test()
# Удаление виджетов — delete widgets
Удаление виджетов из интерфейса осуществляется двумя способами:
pack_forget() , grid_forget() или grid_remove() — сделает виджет временно невидимым. Какой из них вы выберете, зависит от того, используете ли вы сетку или пакет, и хотите ли вы, чтобы сетка запомнила, где она была, чтобы вы могли позже поместить ее обратно в то же место.
destroy() — метод удаляет виджет.
Для примера используем код программы, в которой command=lambda: b.pack_forget() — создается лямбда функция, вызывающая у созданного объекта button метод pack_forget() :
from tkinter import * from tkinter.ttk import * root = Tk() label = Label(text="The button will be hidden. ") label.pack() button = Button(root, text="Hidden me", command=lambda: button.pack_forget()) button.pack() root.mainloop()
Результат выполнения до нажатия кнопки:
Результат выполнения после нажатия кнопки:
# Упражнения
- Напишите простую программу, состоящую из метки (label) и кнопки. При нажатии на кнопку метка должна скрываться.
Результат программы до и после нажатия на кнопку:
- Напишите программу с двумя кнопками отрисованные методом .pack() :
- при нажании первой кнопки она скрывает сама себя.
- при нажатии второй кнопки она отрисовывает первую кнопку на прежнее место.
# Добавление/удаление виджетов — Add/delete widgets
Для добавления и удаления виджетов создадим программу с функцией создания кнопок, которые будут удалять сами себя:
from tkinter import * from tkinter.ttk import * def add_button(): button = Button(text="I am here.)", command=lambda: button.pack_forget()) button.pack() root = Tk() button = Button(root, text="Add button", command=add_button) button.pack() root.mainloop()
Результат программы до и после нажатия на кнопку:
Изменим добавление кнопок слева и добавим счетчик для наглядности удаления: кнопка удаляет саму себя:
from tkinter import * from tkinter.ttk import * i = 1 def add_button(): global i button = Button(text="I am <>".format(i), command=lambda: button.pack_forget()) button.pack(side=LEFT) i += 1 root = Tk() button = Button(root, text="Add button", command=add_button) button.pack() root.mainloop()
Результат программы после добавления и удаления некоторых кнопок:
# Упражнения
- Напишите программу добавляющую кнопки справа, должно получиться следующего вида:
- Напишите программу добавляющую кнопки в сетку — grid по диагонали. Для удаления виджетов используем методы: grid_forget() или grid_remove() . Должно получиться следующего вида:
- Напишите программу добавляющую нопки в сетку — grid в первую колонку и увеличивающую длину заполняемых колонок. Добавление метки: Label(text=»Column <>».format(i)).grid(row=0, column=i) Для размещения и заполнения кнопки используется следующий код: …grid(row=i, column=0, columnspan=i+1, stick=NSEW) Должно получиться следующего вида:
# Добавление/удаление нескольких виджетов
Добавление группы виждетов одновременно с расчетом на дальнейшее возможное их удаление, можно создавать дополнительный фрейм, в него помещать все новые виджеты. При удалении группы виджетов, нужно просто удалить фрейм:
from tkinter import * from tkinter.ttk import * i = 1 def add_widgets(): global i lbl_frm = Labelframe(text="Frame <>".format(i)) lbl_frm.pack() Entry(lbl_frm, text="Text entry <>".format(i)).grid(row=0, column=0, stick=NSEW) button = Button(lbl_frm, text="Delete frame <>".format(i), command=lambda: lbl_frm.destroy()) button.grid(row=0, column=1) i += 1 root = Tk() Button(text="Add button", command=add_widgets).pack() root.mainloop()
Результат программы после добавления и удаления некоторых виджетов:
# Упражнения
- Напишите программу добавляющую Label и кнопку для удаления:
- Напишите программу добавляющую Radiobutton и кнопку для удаления:
- Напишите программу добавляющую Checkbutton, Entry и кнопку для удаления:
- Напишите программу генирующую список задач, с нумерацие и возможностью удаления. Реализуя поведение нумерации, как в нумерованных списках текстовых редакторов. Внесите следующие изменения:
- сгенерированые виджеты сохранять в массив для дальнейшей обработки.
- при удалении поледних виджетов, виджеты сгенерированые заново начнут номерацию с последнего номера отрисованного виджета.
- удаление виджета по середите ведет к удалению виджета из массива переименованию всех виджетов (перерисовки массива)