Giuseppe Marziano
Giuseppe Marziano

Reputation: 69

how to implement dynamic tkinter listboxes?

So I was given some example code of how to essentially control multiple Listboxes within one function, it seems to work during the example code but after implementing i am struggling to see what I've missed out.

Example code:

import tkinter as tk

class MultiListbox(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        for i in range(5):
            lb = tk.Listbox(self, height=10, exportselection=False)
            lb.pack(side="left", fill="y")
            for j in range(10):
                lb.insert("end", f"Listbox {i+1} value {j+1}")
            lb.bind("<Double-1>", self.removeSeq)

    def removeSeq(self, event):
        lb = event.widget
        curselection = lb.curselection()
        index = curselection[0] if curselection else None

        for listbox in self.winfo_children():
            listbox.delete(index)
  
root = tk.Tk()
mlb = MultiListbox(root)
mlb.pack(side="top", fill="both", expand=True)

root.mainloop()

Where I am trying to implement logic:

Imports

import tkinter as tk,tkinter.ttk as ttk, pyautogui, numpy, easygui, cv2, os, time, _thread, re, math, subprocess
from tkinter import BOTH, END, LEFT
pyautogui.FAILSAFE = True

Class

class Acgm003App:
    def __init__(self, master=None):

        
        for i in range(5):
            self.lb = tk.Listbox(self.modeSelect)
            self.lb.configure(background='#2f2a2d', exportselection='false', font='{Arial} 12 {}', foreground='#feffff', height='23')
            self.lb.configure(relief='flat', width='12')
            self.lb.pack(side='left')
            for j in range(10):
                self.lb.insert("end", f"Listbox {i+1},{j+1}")
            self.lb.bind("<Double-1>", self.getIndexLB)

Function

    def getIndexLB(self, event):
        print('hello')
        self.lb = event.widget
        curselection = self.lb.curselection()
        index = curselection[0] if curselection else None

        for listbox in self.lb.winfo_children():
            print(index)
            listbox.delete(index)
    pass

I am just not getting anything back at all, I put print('hello') there just to make sure it was binded correctly, it prints just fine, but no result.

The code is intended to delete listbox items in other listboxes by taking the corresponding index of the curselection, sort of a work around to a tk.treeview.

Let me know if you can help!

Upvotes: 0

Views: 333

Answers (1)

furas
furas

Reputation: 143098

I didn't test it but I think you use it with wrong object.

Original code use

lb = tk.Listbox(self, ...)

to add listbox to self and later it searchs children in self

for listbox in self.winfo_children():

You add listbox to self.modeSelect

tk.Listbox(self.modeSelect, ...)

so you should search children in self.modeSelect

for listbox in self.modeSelect.winfo_children():

But this method can make problem if you add other widgets in self.modeSelect because it will try to use .delete(index) also on other widgets. And then you should check if you get tk.Listbox

    for child in self.modeSelect.winfo_children():
        if isinstance(child, tk.Listbox):
            child.delete(index)

EDIT:

import tkinter as tk

class Acgm003App:

    def __init__(self, master=None):
        
        self.modeSelect = tk.Frame(master)
        self.modeSelect.pack()
        
        # other child in `self.modeSelect`
        self.label = tk.Label(self.modeSelect, text="Hello World")
        self.label.pack(side='top')
        
        for i in range(5):
            self.lb = tk.Listbox(self.modeSelect)
            self.lb.pack(side='left')
            for j in range(10):
                self.lb.insert("end", f"Listbox {i+1},{j+1}")
            self.lb.bind("<Double-1>", self.getIndexLB)

    def getIndexLB(self, event):
        self.lb = event.widget
        curselection = self.lb.curselection()
        index = curselection[0] if curselection else None

        for child in self.modeSelect.winfo_children():
            # check if child is `tk.Listbox` or other widget
            if isinstance(child, tk.Listbox):
                child.delete(index)

root = tk.Tk()

app = Acgm003App(root)

root.mainloop()

Upvotes: 1

Related Questions