Subclasificar Tkinter para crear un Widget personalizado

consulte el siguiente código: (Básicamente, estoy tratando de crear un widget de texto con una barra de desplazamiento vertical mientras conservo todos los métodos / funciones de Tkinter.Text en mi clase)

class ScrollableTextWidget(Tkinter.Text): def __init__(self, parent): self.parent = parent self.Frame = ttk.Frame(self.parent) Tkinter.Text.__init__(self, self.Frame, width=1, height=1) self.__initWidget() def __initWidget(self): self.Frame.grid(sticky="NSEW") self.ScrollbarY = ttk.Scrollbar(self.Frame, orient="vertical", command=self.yview) self.configure(yscrollcommand=self.ScrollbarY.set) self.grid(column=0, row=0, sticky="NSEW") self.ScrollbarY.grid(column=1, row=0, sticky="NS") self.Frame.columnconfigure(0, weight=1) self.Frame.rowconfigure(0, weight=1) 

¿Es correcto crear mi widget personalizado como este o debería colocarlo en un marco y escribir mis propios métodos?

Es muy normal subclasificar un widget para crear uno personalizado. Sin embargo, si este widget personalizado se compone de más de un widget, normalmente se subclase Frame . Por ejemplo, para crear un widget que es un widget de texto con una barra de desplazamiento, haría algo como esto:

 import Tkinter as tk class ScrolledText(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent) self.text = tk.Text(self, *args, **kwargs) self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview) self.text.configure(yscrollcommand=self.vsb.set) self.vsb.pack(side="right", fill="y") self.text.pack(side="left", fill="both", expand=True) class Example(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) self.scrolled_text = ScrolledText(self) self.scrolled_text.pack(side="top", fill="both", expand=True) with open(__file__, "r") as f: self.scrolled_text.text.insert("1.0", f.read()) root = tk.Tk() Example(root).pack(side="top", fill="both", expand=True) root.mainloop() 

Con este enfoque, observe cómo necesita hacer referencia al widget de texto interno al insertar texto. Si desea que este widget se parezca más a un widget de texto real, puede crear una asignación a algunas o todas las funciones del widget de texto. Por ejemplo:

 import Tkinter as tk class ScrolledText(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent) self.text = tk.Text(self, *args, **kwargs) self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview) self.text.configure(yscrollcommand=self.vsb.set) self.vsb.pack(side="right", fill="y") self.text.pack(side="left", fill="both", expand=True) # expose some text methods as methods on this object self.insert = self.text.insert self.delete = self.text.delete self.mark_set = self.text.mark_set self.get = self.text.get self.index = self.text.index self.search = self.text.search class Example(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) self.scrolled_text = ScrolledText(self) self.scrolled_text.pack(side="top", fill="both", expand=True) with open(__file__, "r") as f: self.scrolled_text.insert("1.0", f.read()) root = tk.Tk() Example(root).pack(side="top", fill="both", expand=True) root.mainloop() 

Usaría subclases para proyectos medianos, grandes o para proyectos con soporte en el futuro porque las subclases pueden ser fáciles de reemplazar o actualizar. En cualquier caso, los costos de subclasificación son pequeños. Pero si tu tarea es desechable hazlo sucio y rápido.

En este caso, yo crearía subclases de Frame porque es el widget más general y no necesita reemplazar pack métodos de pack , grid y otros.