¿Por qué se desaconsejan múltiples instancias de Tk?
Considere el siguiente ejemplo:
import tkinter as tk
root = tk.Tk()
root.title("root")
other_window = tk.Tk()
other_window.title("other_window")
root.mainloop()
y también vea el siguiente ejemplo que crea instancias Tk
consecutivas en lugar de a la vez, por lo que hay exactamente una instancia Tk
en un momento dado:
import tkinter as tk
def create_window(window_to_be_closed=None):
if window_to_be_closed:
window_to_be_closed.destroy()
window = tk.Tk()
tk.Button(window, text="Quit", command=lambda arg=window : create_window(arg)).pack()
window.mainloop()
create_window()
- ¿Por qué se considera malo tener múltiples casos de
Tk
? - ¿Se considera el segundo fragmento un poco mejor o sufre las mismas condiciones que el primer código?
¿Por qué se considera malo tener varias instancias de
Tk
?
Tkinter es solo un contenedor de Python alrededor de un intérprete Tcl integrado que importa la biblioteca Tk. Cuando crea una ventana raíz, crea una instancia de un intérprete Tcl.
Cada intérprete de Tcl es una zona de pruebas aislada. Un objeto en un entorno limitado no puede interactuar con objetos en otro. La manifestación más común de esto es que unStringVar
creado en un intérprete no es visible en otro. Lo mismo ocurre con los widgets: no se pueden crear widgets en un intérprete que tenga como widget principal en otro intérprete. Las imágenes son un tercer caso: las imágenes creadas en uno no se pueden utilizar en otro.
Desde un punto de vista técnico, no hay ninguna razón por la que no puedas tener dos instancias Tk
al mismo tiempo. La recomendación en contra se debe a que rara vez existe una necesidad real de tener dos o más intérpretes Tcl distintos, y causa problemas que son difíciles de comprender para los principiantes.
¿Se considera el segundo fragmento un poco mejor o sufre las mismas condiciones que el primer código?
Es imposible decir si el segundo ejemplo de la pregunta es mejor o no sin saber lo que estás tratando de lograr. Probablemente no sea mejor ya que, nuevamente, rara vez hay un momento en el que realmente necesites dos instancias.
La mejor solución el 99,9% de las veces es crear exactamente una instancia que Tk
utilice durante la vida de su programa. Si necesita una segunda ventana o una posterior, cree instancias de Toplevel
. En pocas palabras, así es como se diseñaron tkinter y el intérprete Tcl/Tk subyacente.
No estoy de acuerdo con que la tkinter
comunidad desaconseje el uso de ventanas múltiples tk.Tk
. Puedes tener varias tk.Tk
ventanas. Usar múltiples instancias de tk.Tk
es la única forma de crear ventanas que sean verdaderamente independientes entre sí. El único error que comete la mayoría de las personas al crear varias tk.Tk
ventanas es que se olvidan de pasarlas master=...
al crear PhotoImage
s/ StringVar
s/ IntVar
s/...
Por ejemplo, mira este código:
import tkinter as tk
root = tk.Tk()
root2 = tk.Tk()
variable = tk.StringVar() # Add `master=root2` to fix the problem
entry = tk.Entry(root2, textvariable=variable)
entry.bind("<Return>", lambda e: print(repr(variable.get())))
entry.pack()
root.mainloop()
El código anterior no funciona. master=root2
Si lo agrega tk.StringVar()
, funcionará perfectamente bien. Esto se debe a que tkinter
almacena la primera instancia tk.Tk()
de tk._default_root
. Luego, si no ingresa master=...
, se asumirá que deseaba abrir la ventana tk._default_root
.
Otra cosa que la gente se equivoca es cuántas veces se debe .mainloop()
llamar. Maneja eventos de todas tk.Tk
las ventanas que están activas, por lo que solo necesitas una .mainloop()
.
Para las personas que no están de acuerdo, me interesaría un ejemplo de dónde un problema real es causado por las múltiples tk.Tk
ventanas.
La mejor referencia que he encontrado hasta ahora es la sección Aplicación de Windows del tkinterbook :
En los ejemplos sencillos que hemos usado hasta ahora, sólo hay una ventana en la pantalla; la ventana raíz. Esto se crea automáticamente cuando llamas al constructor Tk .
y
Si necesita crear ventanas adicionales, puede utilizar el widget Toplevel . Simplemente crea una nueva ventana en la pantalla, una ventana que se ve y se comporta de forma muy parecida a la ventana raíz original.
Mi opinión es que una Tk
instancia crea un Toplevel
widget, además de cosas como mainloop
, de las cuales debería haber solo una.