Home > database >  delete label when deselecting item from a listbox tkinter
delete label when deselecting item from a listbox tkinter

Time:10-16

Once again I need your knowledge. I have written a small script to display a listbox and I would like to do two things.

I) : print in a label on the right side of the window the item selected and delete the label if user is deselecting the item
II) : Add a line between each label if some items are selected
I can display items but in a single line and by deselecting items in the listbox, label is not removed
Thanks in advance for your help

from tkinter import *
import tkinter as tk


class Application(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.previous_selected = None
        self.listNumber = ['One', 'Two', 'Three', 'Four', 'Five', 'Six']

        self.labellist = tk.Label(self, text=' Select a number : ')
        self.labellist.place(x=40, y=30)

        self.frame = Frame(self)
        self.frame.place(x=200, y=30)
        self.list = Listbox(self.frame, exportselection=False, height=5, selectmode="multiple")
        self.list.pack(side='left', fill='y')

        for each_item in range(len(self.listNumber)):
            self.list.insert(END, self.listNumber[each_item])
        self.scrollbar = Scrollbar(self.frame, orient="vertical", command=self.list.yview)
        self.scrollbar.pack(side='right', fill='y')
        self.list.config(yscrollcommand=self.scrollbar.set)

        self.list.bind('<<ListboxSelect>>',self.printSelection)

        self.buttonExecute = tk.Button(self, text='Execute', fg='White', bg='dark green', height=1, width=10, command=self.destroy)
        self.buttonExecute.place(x=225, y=150)

    def printSelection(self, evt):
        values = [self.list.get(idx) for idx in self.list.curselection()]
        self._label = tk.Label(self, text=' Number selected  ' ', '.join(values) '\n')
        self._label.place(x=350, y=30)
    
        if self.list.curselection() == self.previous_selected:
            self._label.place_forget()


if __name__ == "__main__":
    app = Application()
    app.geometry("600x250")
    app.mainloop()

CodePudding user response:

Here is an update on your code. I've simplified printSelection by creating all Labels with blank text. This means every item in self.list has a unique Label.

I also changed pack managed objects to place managed.

Not sure if this is exactly what you are looking for but now it works and should give you an idea on how to proceed.

Also I have inserted remarks into code that describe changes.

import tkinter as tk

class Application(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.previous_selected = None
        self.listNumber = ["One", "Two", "Three", "Four", "Five",
                           "Six", "Seven", "Eight", "Nine"]
        self._label = dict() # label store
        # Using place with x, y
        self.labellist = tk.Label(self, anchor = tk.NW, text = " Select a number : ")
        self.labellist.place(x = 100, y = 10)
        # Using place with x, y, width, height
        self.frame = tk.Frame(self)
        self.frame.place(x = 100, y = 30, width = 300, height = 100)
        # Using place with x, y, width, height
        self.list = tk.Listbox(
            self.frame, exportselection = False, activestyle = tk.NONE,
            height = 5, selectmode = "extended")
        self.list.place(x = 2, y = 2, width = 200, height = 100)
        # Simplified populating list
        for each_item in self.listNumber:
            self.list.insert(tk.END, each_item)
        # Using place with x, y, width, height
        self.scrollbar = tk.Scrollbar(
            self.frame, orient = "vertical", command = self.list.yview)
        self.scrollbar.place(x = 210, y = 2, width = 12, height = 100)
        self.list.config(yscrollcommand = self.scrollbar.set)
        # Pre create all labels so that each label has a unique position
        for i, a in enumerate(self.listNumber):
            L = tk.Label(self, text = "")
            # Using place with x, y
            L.place(x = 350, y = i * 20)
            self._label[a] = L

        self.list.bind("<<ListboxSelect>>",self.printSelection)

        self.buttonExecute = tk.Button(
            self, text = "Execute", fg = "White",
            bg = "dark green", height = 1, width = 10, command = self.destroy)
        # Using place with x, y
        self.buttonExecute.place(x = 230, y = 140)

    def printSelection(self, evt):
        index = self.list.curselection()[ 0 ] # grab the index
        item = self.list.get(index)
        if self._label[item]["text"] == "":
            self._label[item]["text"] = f"Number selected {item}    "
        else:
            self._label[item]["text"] = ""

if __name__ == "__main__":
    app = Application()
    app.geometry("515x250")
    app.mainloop()

To use your original selectmode settings printSelection needs to change.

    def printSelection(self, evt):
        for i,item in enumerate(self.listNumber):
            if self.list.select_includes(i):
                self._label[item]["text"] = f"Number selected {item}    "
            else:
                self._label[item]["text"] = ""
  • Related