user7864036
user7864036

Reputation:

Deleting selected items from the treeview, as well as from the list at the same time

I created a simple to do tasks GUI application . Besides adding items to the treeview, I add them to the list of Task objects. I want to delete all selected items from the treeview, as well as from the list (self.tasks) at the same time.

I was able to delete only one selected item from the treeview, I don't know how to delete multiple selected items. Also, I don't know how to find and delete the selected item in the list I have.

Here is what I have done so far:

#!usr/bin/python3

# Todo.py
# GUI program to manage to-do tasks

from tkinter import *
from tkinter import ttk

class Task:

    def __init__(self, subject=None, priority=None):
        self.subject = subject
        self.priority = priority


class Todo(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.master = master
        self.master.resizable(width=False, height=False)
        self.master.title('Todo')
        self.master.geometry('237x306')
        self.create_widgets()
        self.tasks = []

    def create_widgets(self):
        self.search_frame = Frame(self.master)
        self.search_frame.grid(row=0)

        self.treeview_frame = Frame(self.master)
        self.treeview_frame.grid(row=1)

        self.buttons_frame = Frame(self.master)
        self.buttons_frame.grid(row=2)

        self.search_text = Entry(self.search_frame,
                                 width=29)
        self.search_text.grid(row=0)

        self.treeview = ttk.Treeview(self.treeview_frame,
                                     height=12,
                                     columns=('Subject', 'Priority'))
        self.treeview.grid(row=0)
        self.treeview.column('#0', minwidth=0, width=30, stretch=NO)
        self.treeview.heading('#0', text="#")
        self.treeview.column('Subject', minwidth=0, width=147, stretch=NO)
        self.treeview.heading('Subject', text='Subject')
        self.treeview.column('Priority', minwidth=0, width=57, stretch=NO)
        self.treeview.heading('Priority', text='Priority')
        self.i = 0

        self.add_button = Button(self.buttons_frame,
                                 text='Add',
                                 command=self.add_item)
        self.add_button.grid(row=0, column=0)

        self.remove_button = Button(self.buttons_frame,
                                 text='Remove',
                                 command=self.remove_item)

        self.remove_button.grid(row=0, column=1)

        self.edit_button = Button(self.buttons_frame,
                                  text='Edit',
                                  command=self.edit_item)
        self.edit_button.grid(row=0, column=2)

        self.save_button = Button(self.buttons_frame,
                                  text='Save',
                                  command=self.save_item)
        self.save_button.grid(row=0, column=3)

    def create_item_dialog(self):
        self.item_dialog = Toplevel(self.master)
        self.item_dialog.geometry('202x197')

        self.item_dialog_text_frame = Frame(self.item_dialog)
        self.item_dialog_text_frame.grid(row=0, sticky=W)

        self.item_dialog_combobox_frame = Frame(self.item_dialog)
        self.item_dialog_combobox_frame.grid(row=1, sticky=W)

        self.item_dialog_another_frame = Frame(self.item_dialog)
        self.item_dialog_another_frame.grid(row=2)

        self.item_dialog_buttons_frame = Frame(self.item_dialog)
        self.item_dialog_buttons_frame.grid(row=3)

        self.subject_label = Label(self.item_dialog_text_frame,
                                   text='Subject:')
        self.subject_label.grid(row=0, sticky=W)

        self.subject_text = Text(self.item_dialog_text_frame,
                                 width=28,
                                 height=9)
        self.subject_text.grid(row=1)

        self.priority_label = Label(self.item_dialog_combobox_frame,
                                   text='Priority:')

        self.priority_label.grid(row=0, column=0, sticky=W)

        self.priority_combobox = ttk.Combobox(self.item_dialog_combobox_frame,
                                              width=17)
        self.priority_combobox.grid(row=0, column=1)
        self.priority_combobox['values'] = ('High', 'Medium', 'Low')

        self.item_dialog_ok_button = Button(self.item_dialog_buttons_frame,
                                            width=9,
                                            text='OK',
                                            command=self.add)
        self.item_dialog_ok_button.grid(row=0, column=0)

        self.item_dialog_cancel_button = Button(self.item_dialog_buttons_frame,
                                                width=9,
                                                text='Cancel',
                                                command = self.close_item_dialog)
        self.item_dialog_cancel_button.grid(row=0, column=1)


        self.item_dialog.wait_window()

    def close_item_dialog(self):
        self.item_dialog.destroy()

    def add_item(self):
        self.create_item_dialog()

    def add(self):
        t = Task(self.subject_text.get('1.0', '1.0 lineend'), self.priority_combobox.get())

        self.treeview.insert('', END, text=str(self.i), values=(t.subject, t.priority))
        self.i = self.i + 1
        self.tasks.append(t)

        self.close_item_dialog()

    def remove_item(self):
        selected_item = self.treeview.selection()[0]
        self.treeview.delete(selected_item)

    def edit_item(self):
        pass

    def save_item(self):
        pass

def main():
    root = Tk()
    Todo(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Upvotes: 1

Views: 9950

Answers (1)

Billal BEGUERADJ
Billal BEGUERADJ

Reputation: 22744

1. Deleting all selected items

The treeview's selection() method returns the lists of the selected items. But in remove_item() you coded this line:

selected_item = self.treeview.selection()[0]

Which thing means you are interested only in the first selected item among the list of the selected items.

If you take this information in consideration, you can achieve your goal by modifying remove_item() consequently as follows:

def remove_item(self):
   selected_items = self.treeview.selection()        
   for selected_item in selected_items:          
      self.treeview.delete(selected_item)

2. Updating the tasks list

I think you want to update self.tasks[] whenever an item (or a group of items) is selected and deleted by the user.

You can do that within the same remove_item() function mention above.

For this, notice that the items you add to self.treeview are dictionaries following this form:

{'open': 0, 'tags': '', 'image': '', 'values': ['cpp', 'Medium'], 'text': '1'}

The key of such a dictionary which is useful for your case is value because it allows us to compare it to each instance of Task() class.

To access the value of that key you must run this: self.treeview.item(selected_item)['values']

You get then a list which corresponds to the dictionary of a Task() instance.

So you have to compare the Task() instance (self.tasks[some_index]) with the value of the key mentioned above.

May be the code is better to understand:

 def remove_item(self):
        selected_items = self.treeview.selection()
        for selected_item in selected_items:  
           # Updating selfs.tasks[] through this loop            
           for i in range(len(self.tasks)):
               if self.tasks[i].subject == self.treeview.item(selected_item)['values'][0]:
                   self.tasks.pop(i) # Remove the corresponding item
                   # Make sure the list is updated:
                   print('length: {}'.format(len(self.tasks)))
                   break          
           self.treeview.delete(selected_item)

Demo

Let us insert these 7 items:

enter image description here

I selected 2 of them to delete them. The output on Terminal shows the list is updated:

enter image description here

Upvotes: 4

Related Questions