I created entries and labels by loops. If user click the button there will be new entries and lables in two-two seperated row. Now I want to delete them by other button clicking, but labels are not deletable -only entries are.
My other problem is I want to delete just only the last widgets that were added by one clicking. To make it clear: I want to delete the last 18-18 labels and entries by one clicking. Currently, all the added entries so far will be deleted. The labels are not at all. Here is the relevant code:
self._1thLabel_list = ['Label1', 'Label2', 'Label3', 'Label4', 'Label5',
'Label6', 'Label7', 'Label8', 'Label9']
self._2thLabel_list = ['Label10', 'Label11', 'Label12', 'Label13', 'Label14',
'Label15', 'Label16', 'Label17', 'Label18']
nothingList2 = []
self.col = 4
for j in range(len(self._1thLabel_list)):
self.myLab = Label(root, text=self._1thLabel_list[j]).grid(row=0, column=j+1)
for k in range(1):
self.myEntry_loop = Entry(root)
self.myEntry_loop.grid(row=k + 1, column=j+1, pady=10, padx=10)
self.myEntry_loop_2 = Entry(root)
self.myEntry_loop_2.grid(row=k + 3, column=j + 1, pady=10, padx=10)
nothingList2.append(self.myEntry_loop)
nothingList2.append(self.myEntry_loop_2)
for l in range(len(self._2thLabel_list)):
self.myLab_2 = Label(root, text=self.mylist_2[l]).grid(row=2, column=l + 1)
self.myButton_newWidgets = Button(root, text="Add", command=self.Add)
self.myButton_newWidgets.grid(row=self.col, column=4)
self.myButton_deleteWidgets = Button(root, text="Delete", command=self.deleteThem)
self.myButton_deleteWidgets.grid(row=self.col, column=5)
And here is how try to delete them:
def deleteThem(self):
for v in range(18):
nothingList2.pop(0)
for dele in nothingList2:
dele.destroy() # Here, it is deleting entries but delete all of them. I want just delete the last 18 of them.
for w in range(9):
self._1thLabel_list.pop(0)
for delet in self._1thLabel_list:
delet.destroy() # I got "AttributeError: 'str' object has no attribute 'destroy'" error in this line
for x in range(9):
self._2thLabel_list.pop(0)
for delet2 in self._2thLabel_list:
delet2.destroy()
Here is a solution (explanation below):
from tkinter import Tk, Button
root = Tk()
removable_widget_dict = {}
class RemovableWidget(Button):
def __init__(self, parent, title, key):
Button.__init__(self, parent)
self.key = key
self.config(text=title)
self.pack()
def delete(self):
self.destroy()
removable_widget_dict.pop(self.key)
for i in range(10):
key = f'item{i}'
removable_widget_dict[key] = RemovableWidget(root, f'Button {i}', key)
for key in removable_widget_dict.keys():
if key == 'item5':
removable_widget_dict[key].delete()
break
root.mainloop()
Explanation:
First of I would like to mention that this is something I came up with (at least similar to this) when doing a personal project so all of this comes from experience in a sense that this may not be the best solution but it certainly works.
After doing the basic stuff with tkinter (root = Tk()
, root.mainloop()
) You create a dictionary which will sort of store classes. Now classes are an important factor here since each instance of a class can act independently which cannot really be achieved with functions at least not as easy.
So then You create a class for whatever widget You need, You can create multiple classes for multiple widgets or somehow merge them all into one (don't know how that would work) but lets stick to one class for one type of widget.
In this class You define all the basic stuff You would for a widget but also You add an important argument "key". This is not as important but certainly is necessary because You do not want to leave unused classes in memory (don't know about the technical aspects but imo it keeps everything more clean especially if You have to read it[dictionary] for some reason)
Then You define the deletion function and here is where the independence of class instances comes in: for each class instance You will be able to call this function which will only affect that class instance. So now in this function You will destroy the widget that class created (in this case the button in self.button
) or multiple widgets. and then the cleanup part comes in: You globally define the dictionary and then delete the "key" from it. and the key also makes it easier to access the class instance for other reasons.
The final note. You can access the classes who are stored in dictionaries functions like this: dictionary[key].that_class_function