Tienes dos errores a grandes rasgos:
Estás intentando resolver el problema usado dos paradigmas de la POO conjuntamente, herencia y composición.
El otro problema es el de "individualizar". Para que cada instancia de tu Editable ListBox
se se comporte de forma individual al hacer doble click debes usar atributos de instancia para definir select
y entrylistBox
y no variables globales. Al usar variables globales todas las instancias de la clase comparten estos dos valores cosa que no quieres obviamente. Para más información mirate:
Usando herencia
Tu clase debe heredar de tkinter.ListBox
(cosa que ya hace) y además se debe invocar de forma explícita al inicializador (__init__
) de la clase padre (tkinter.ListBox
). Esto se debe a que en la clase hija EditableListbox
sobrescribes el método __init__
heredado del padre que no va a ser llamado por tanto al instanciar tu clase. el problema es que el init de la clase padre contiene código que permite a un ListBox
comportarse como tal por lo que se debe llamar a su inicializador de forma explícita desde el __init__
de la clase hija. esto podemos hacerlo de forma directa:
ListBox.__init__(self, ventana)
o usando super
(superclass):
super().__init__(ventana)
esto causa tu error al intentar insertar elementos en la lista.
El código podría quedar algo así:
import tkinter as tk
from tkinter import Entry
from tkinter import Listbox
from tkinter.font import Font
class EditListBox(tk.Listbox):
def __init__(self, ventana, posx, posy):
super().__init__(ventana, width=27)
self.ventana = ventana
self.config(borderwidth=2,
highlightthickness=4,
highlightcolor="#0000ff",
selectforeground="#ffffff",
selectbackground="#00aa00",
selectborderwidth=2,
font=Font(family="Sans Serif", size=10),
activestyle=tk.NONE
)
self.bind('<Double-Button-1>', self.doble_click)
self.place(x=posx,y=posy)
self.select = None
self.entrylistBox = None
def doble_click(self,_):
if self.size() > 0:
self.config(state="disabled", disabledforeground="#A2A2A2")
self.select = self.curselection()
_, y, _, h = self.bbox(self.curselection())
x = self.winfo_x() + 5
y += self.winfo_y()
w = self.winfo_width() - 12
valor = self.get(self.curselection())
self.entrylistBox = Entry(self.ventana)
self.entrylistBox.config(font=Font(family="Sans Serif", size=10))
self.entrylistBox.focus_set()
self.entrylistBox.place(x=x, y=y, width=w, height=h)
self.entrylistBox.config(highlightthickness=1, highlightcolor="green")
self.entrylistBox.insert(0, valor)
self.entrylistBox.bind('<Return>', self.key_enter)
def key_enter(self,_):
self.entrylistBox.place_forget()
self.config(state="normal")
valor_ = self.entrylistBox.get()
self.delete(self.select)
self.insert(self.select, valor_)
ventana1 = tk.Tk()
ventana1.geometry("670x320")
listBox1 = EditListBox(ventana1, 10, 30)
listBox1.insert(0, "Prueba")
listBox1 = EditListBox(ventana1, 350, 30)
listBox1.insert(0, "Prueba")
ventana1.mainloop()
Usando composición
En este caso tu clase no debe heredar de tkinter.ListBox
, sino que actúa como un mero contenedor de dicho widget:
import tkinter as tk
from tkinter import Entry
from tkinter import Listbox
from tkinter.font import Font
class EditListBox:
def __init__(self, ventana, posx, posy):
self.ventana = ventana
self.listbox = Listbox(ventana, width=27)
self.listbox.config(borderwidth=2,
highlightthickness=4,
highlightcolor="#0000ff",
selectforeground="#ffffff",
selectbackground="#00aa00",
selectborderwidth=2,
font=Font(family="Sans Serif", size=10),
activestyle=tk.NONE
)
self.listbox.bind('<Double-Button-1>', self.doble_click)
self.listbox.place(x=posx,y=posy)
self.select = None
self.entrylistBox = None
def doble_click(self,_):
if self.listbox.size() > 0:
self.listbox.config(state="disabled", disabledforeground="#A2A2A2")
self.select = self.listbox.curselection()
_, y, _, h = self.listbox.bbox(self.listbox.curselection())
x = self.listbox.winfo_x() + 5
y += self.listbox.winfo_y()
w = self.listbox.winfo_width() - 12
valor = self.listbox.get(self.listbox.curselection())
self.entrylistBox = Entry(self.ventana)
self.entrylistBox.config(font=Font(family="Sans Serif", size=10))
self.entrylistBox.focus_set()
self.entrylistBox.place(x=x, y=y, width=w, height=h)
self.entrylistBox.config(highlightthickness=1, highlightcolor="green")
self.entrylistBox.insert(0, valor)
self.entrylistBox.bind('<Return>', self.key_enter)
def key_enter(self,_):
self.entrylistBox.place_forget()
self.listbox.config(state="normal")
valor_ = self.entrylistBox.get()
self.listbox.delete(self.select)
self.listbox.insert(self.select, valor_)
ventana1 = tk.Tk()
ventana1.geometry("670x320")
listBox1 = EditListBox(ventana1, 10, 30)
listBox1.listbox.insert(0, "Prueba")
listBox1 = EditListBox(ventana1, 350, 30)
listBox1.listbox.insert(0, "Prueba")
ventana1.mainloop()