Abogo por un enfoque orientado a objetos. Esta es la plantilla con la que empiezo:
# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
<create the rest of your GUI here>
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Las cosas importantes a tener en cuenta son:
No uso una importación de comodines. Importo el paquete como "tk", lo que requiere que prefijo todos los comandos con tk.
. Esto evita la contaminación del espacio de nombres global, además hace que el código sea completamente obvio cuando está utilizando clases Tkinter, clases ttk o algunas propias.
La aplicación principal es una clase . Esto le brinda un espacio de nombres privado para todas sus devoluciones de llamada y funciones privadas, y generalmente facilita la organización de su código. En un estilo de procedimiento, debe codificar de arriba hacia abajo, definiendo funciones antes de usarlas, etc. Con este método no lo hace, ya que en realidad no crea la ventana principal hasta el último paso. Prefiero heredar tk.Frame
solo porque normalmente empiezo creando un marco, pero de ninguna manera es necesario.
Si su aplicación tiene ventanas de nivel superior adicionales, le recomiendo hacer de cada una de ellas una clase separada, heredando de tk.Toplevel
. Esto le brinda las mismas ventajas mencionadas anteriormente: las ventanas son atómicas, tienen su propio espacio de nombres y el código está bien organizado. Además, facilita poner cada uno en su propio módulo una vez que el código comienza a crecer.
Finalmente, es posible que desee considerar el uso de clases para cada parte importante de su interfaz. Por ejemplo, si está creando una aplicación con una barra de herramientas, un panel de navegación, una barra de estado y un área principal, puede crear cada una de esas clases. Esto hace que su código principal sea bastante pequeño y fácil de entender:
class Navbar(tk.Frame): ...
class Toolbar(tk.Frame): ...
class Statusbar(tk.Frame): ...
class Main(tk.Frame): ...
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.statusbar = Statusbar(self, ...)
self.toolbar = Toolbar(self, ...)
self.navbar = Navbar(self, ...)
self.main = Main(self, ...)
self.statusbar.pack(side="bottom", fill="x")
self.toolbar.pack(side="top", fill="x")
self.navbar.pack(side="left", fill="y")
self.main.pack(side="right", fill="both", expand=True)
Dado que todas esas instancias comparten un padre común, el padre efectivamente se convierte en la parte "controlador" de una arquitectura modelo-vista-controlador. Entonces, por ejemplo, la ventana principal podría colocar algo en la barra de estado llamando self.parent.statusbar.set("Hello, world")
. Esto le permite definir una interfaz simple entre los componentes, lo que ayuda a mantener el acoplamiento al mínimo.