Saltar al contenido

¿La mejor forma de estructurar una aplicación tkinter?

Solución:

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 utilizo una importación de comodines. Importo el paquete como “tk”, lo que requiere que anteponga todos los comandos con tk.. Esto evita la contaminación global del espacio de nombres, además de que hace que el código sea completamente obvio cuando usa clases Tkinter, clases ttk o algunas de las suyas.

  • 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, en general, facilita la organización de su código. En un estilo de procedimiento, debe codificar de arriba hacia abajo, definir 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 de 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, recomiendo convertir cada una de ellas en 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 la colocación de 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 se convierte efectivamente en la parte “controladora” 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.

Poner cada una de sus ventanas de nivel superior en su propia clase separada le brinda la reutilización del código y una mejor organización del código. Cualquier botón y método relevante que esté presente en la ventana debe definirse dentro de esta clase. Aquí hay un ejemplo (tomado de aquí):

import tkinter as tk

class Demo1:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.button1 = tk.Button(self.frame, text="New Window", width = 25, command = self.new_window)
        self.button1.pack()
        self.frame.pack()
    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = Demo2(self.newWindow)

class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text="Quit", width = 25, command = self.close_windows)
        self.quitButton.pack()
        self.frame.pack()
    def close_windows(self):
        self.master.destroy()

def main(): 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Ver también:

  • simple hola mundo de tkinter docs
  • Código de ejemplo de Tkinter para múltiples ventanas, ¿por qué los botones no se cargan correctamente?
  • Tkinter: Cómo mostrar / ocultar una ventana

Espero que ayude.

Esta no es una mala estructura; funcionará bien. Sin embargo, debe tener funciones en una función para ejecutar comandos cuando alguien hace clic en un botón o algo

Entonces, lo que podría hacer es escribir clases para estos y luego tener métodos en la clase que manejen comandos para los clics de botones y demás.

He aquí un ejemplo:

import tkinter as tk

class Window1:
    def __init__(self, master):
        pass
        # Create labels, entries,buttons
    def button_click(self):
        pass
        # If button is clicked, run this method and open window 2


class Window2:
    def __init__(self, master):
        #create buttons,entries,etc

    def button_method(self):
        #run this when button click to close window
        self.master.destroy()

def main(): #run mianloop 
    root = tk.Tk()
    app = Window1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Por lo general, los programas tk con múltiples ventanas son múltiples clases grandes y en el __init__ todas las entradas, etiquetas, etc.se crean y luego cada método es para manejar eventos de clic de botón

Realmente no hay una manera correcta de hacerlo, lo que sea que funcione para usted y haga el trabajo siempre que sea legible y pueda explicarlo fácilmente porque si no puede explicar fácilmente su programa, probablemente haya una mejor manera de hacerlo. .

Eche un vistazo a Thinking in Tkinter.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *