widgets w3schools standard library instalar docs python tkinter

python - w3schools - La mejor forma de estructurar una aplicación tkinter



tkinter python 2.7 install (7)

La siguiente es la estructura general de mi programa python tkinter típico.

def funA(): def funA1(): def funA12(): # stuff def funA2(): # stuff def funB(): def funB1(): # stuff def funB2(): # stuff def funC(): def funC1(): # stuff def funC2(): # stuff root = tk.Tk() button1 = tk.Button(root, command=funA) button1.pack() button2 = tk.Button(root, command=funB) button2.pack() button3 = tk.Button(root, command=funC) button3.pack()

funA funB y funC mostrarán otras ventanas de Toplevel con widgets cuando el usuario haga clic en el botón 1, 2, 3.

Me pregunto si esta es la forma correcta de escribir un programa python tkinter? Claro, funcionará incluso si escribo de esta manera, pero ¿es la mejor manera? Suena estúpido, pero cuando veo los códigos escritos por otras personas, su código no está mal con muchas funciones y la mayoría tienen clases.

¿Hay alguna estructura específica que debamos seguir como una buena práctica? ¿Cómo debo planificar antes de comenzar a escribir un programa de Python?

Sé que no existen las mejores prácticas en programación y tampoco las estoy pidiendo. Solo quiero algunos consejos y explicaciones para mantenerme en la dirección correcta ya que estoy aprendiendo Python por mí mismo.


Abogo por un enfoque orientado a objetos. Esta es la plantilla con la que comienzo:

# 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 para notar son:

  • No uso una importación de comodines. Importación el paquete como "tk", que requiere que prefijo 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 está utilizando clases Tkinter, clases ttk o algunas propias.

  • La aplicación principal es una clase . Esto le proporciona un espacio de nombres privado para todas sus devoluciones de llamadas y funciones privadas, y generalmente hace que sea más fácil organizar su código. En un estilo de procedimiento, tiene que codificar top-down, definir funciones antes de usarlas, etc. Con este método no lo hace, ya que no crea la ventana principal hasta el último paso. Prefiero heredar de tk.Frame solo porque normalmente comienzo creando un marco, pero de ninguna manera es necesario.

Si su aplicación tiene ventanas adicionales a nivel superior, recomiendo hacer de cada una de ellas una clase separada, heredando de tk.Toplevel . Esto le brinda todas las ventajas mencionadas anteriormente: las ventanas son atómicas, tienen su propio espacio de nombres y el código está bien organizado. Además, hace que sea fácil poner cada uno en su propio módulo una vez que el código comienza a ser grande.

Por último, 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 hacer 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 elemento primario común, el elemento primario 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 al llamar a self.parent.statusbar.set("Hello, world") . Esto le permite definir una interfaz simple entre los componentes, ayudando a mantener el acoplamiento al mínimo.


Al colocar cada una de las ventanas de nivel superior en su propia clase separada, se obtiene una nueva utilización del código y una mejor organización del código. Todos los botones y métodos relevantes que están presentes en la ventana se deben definir dentro de esta clase. Aquí hay un ejemplo (tomado de here ):

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:

Espero que ayude.



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

Entonces, lo que podrías hacer es escribir clases para estos y luego tener métodos en la clase que manejan los comandos para los clics del botón y demás.

Aquí hay 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 = Demo1(root) root.mainloop() if __name__ == ''__main__'': main()

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

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

Eche un vistazo a Pensar en Tkinter .


OOP debe ser el enfoque y el frame debe ser una variable de clase en lugar de una variable de instancia .

from Tkinter import * class App: def __init__(self, master): frame = Frame(master) frame.pack() self.button = Button(frame, text="QUIT", fg="red", command=frame.quit) self.button.pack(side=LEFT) self.slogan = Button(frame, text="Hello", command=self.write_slogan) self.slogan.pack(side=LEFT) def write_slogan(self): print "Tkinter is easy to use!" root = Tk() app = App(root) root.mainloop()

Referencia: http://www.python-course.eu/tkinter_buttons.php


Personalmente, no uso el enfoque orientado objetado, principalmente porque a) solo se interpone en el camino; b) nunca volverás a utilizar eso como un módulo.

pero algo que no se discute aquí, es que debes usar threading o multiprocesamiento. Siempre. de lo contrario, su solicitud será horrible.

simplemente haga una prueba simple: comience una ventana, y luego busque alguna URL o cualquier otra cosa. Los cambios son que su UI no se actualizará mientras se realiza la solicitud de la red. Es decir, su ventana de aplicación se romperá. dependa del sistema operativo en el que se encuentre, pero la mayoría de las veces no volverá a dibujar, todo lo que arrastre por la ventana quedará grabado en él, hasta que el proceso vuelva al TK mainloop.


Probablemente la mejor manera de aprender cómo estructurar su programa es leyendo el código de otras personas, especialmente si se trata de un programa grande al que han contribuido muchas personas. Después de mirar el código de muchos proyectos, debe hacerse una idea de cuál debería ser el estilo de consenso.

Python, como idioma, es especial en cuanto a que hay algunas pautas sólidas sobre cómo debe formatear su código. El primero es el llamado "Zen de Python":

  • Hermoso es mejor que feo.
  • Explícito es mejor que implícito.
  • Simple es mejor que complejo.
  • Complejo es mejor que complicado.
  • Flat es mejor que anidado.
  • Sparse es mejor que denso.
  • La legibilidad cuenta
  • Los casos especiales no son lo suficientemente especiales como para romper las reglas.
  • Aunque la practicidad supera a la pureza.
  • Los errores nunca deberían pasar silenciosamente.
  • A menos que esté explícitamente silenciado.
  • En vista de la ambigüedad, rechace la tentación de adivinar.
  • Debería haber una, y preferiblemente solo una, forma obvia de hacerlo.
  • Aunque de esa manera puede no ser obvio al principio a menos que seas holandés.
  • Ahora es mejor que nunca.
  • Aunque nunca es a menudo mejor que ahora.
  • Si la implementación es difícil de explicar, es una mala idea.
  • Si la implementación es fácil de explicar, puede ser una buena idea.
  • Los espacios de nombres son una gran idea: ¡hagamos más de eso!

En un nivel más práctico, está PEP8 , la guía de estilo para Python.

Con eso en mente, diría que su estilo de código no encaja, particularmente las funciones anidadas. Encuentre una manera de alisarlos, ya sea mediante el uso de clases o moviéndolos a módulos separados. Esto hará que la estructura de su programa sea mucho más fácil de entender.