tkinter
Meerdere vensters (TopLevel-widgets)
Zoeken…
Verschil tussen Tk en Toplevel
Tk
is de absolute root van de applicatie, het is de eerste widget die moet worden gestart en de GUI wordt afgesloten wanneer deze wordt vernietigd.
Toplevel
is een venster in de toepassing. Als u het venster sluit, worden alle widgets voor kinderen die op dat venster zijn geplaatst {1} vernietigd, maar wordt het programma niet afgesloten.
try:
import tkinter as tk #python3
except ImportError:
import Tkinter as tk #python2
#root application, can only have one of these.
root = tk.Tk()
#put a label in the root to identify the window.
label1 = tk.Label(root, text="""this is root
closing this window will shut down app""")
label1.pack()
#you can make as many Toplevels as you like
extra_window = tk.Toplevel(root)
label2 = tk.Label(extra_window, text="""this is extra_window
closing this will not affect root""")
label2.pack()
root.mainloop()
Als uw python-programma slechts één toepassing vertegenwoordigt (wat het bijna altijd zal doen), zou u slechts één Tk
instantie moeten hebben, maar u kunt zoveel Toplevel
vensters maken als u wilt.
try:
import tkinter as tk #python3
except ImportError:
import Tkinter as tk #python2
def generate_new_window():
window = tk.Toplevel()
label = tk.Label(window, text="a generic Toplevel window")
label.pack()
root = tk.Tk()
spawn_window_button = tk.Button(root,
text="make a new window!",
command=generate_new_window)
spawn_window_button.pack()
root.mainloop()
{1}: als een Topniveau ( A = Toplevel(root)
) het bovenliggende niveau is van een ander Topniveau ( B = Toplevel(A)
), wordt venster B ook gesloten als u venster A sluit.
de vensterstapel rangschikken (de .lift-methode)
Het meest basale geval om een bepaald venster boven het andere te tillen, roept u gewoon de .lift()
-methode op dat venster aan ( Toplevel
of Tk
)
import tkinter as tk #import Tkinter as tk #change to commented for python2
root = tk.Tk()
for i in range(4):
#make a window with a label
window = tk.Toplevel(root)
label = tk.Label(window,text="window {}".format(i))
label.pack()
#add a button to root to lift that window
button = tk.Button(root, text = "lift window {}".format(i), command=window.lift)
button.grid(row=i)
root.mainloop()
Als dat venster echter wordt vernietigd terwijl het probeert op te tillen, zal dit een fout veroorzaken:
Exception in Tkinter callback
Traceback (most recent call last):
File "/.../tkinter/__init__.py", line 1549, in __call__
return self.func(*args)
File "/.../tkinter/__init__.py", line 785, in tkraise
self.tk.call('raise', self._w, aboveThis)
_tkinter.TclError: bad window path name ".4385637096"
Vaak wanneer we proberen een bepaald venster voor de gebruiker te plaatsen maar het was gesloten, is een goed alternatief om dat venster opnieuw te maken:
import tkinter as tk #import Tkinter as tk #change to commented for python2
dialog_window = None
def create_dialog():
"""creates the dialog window
** do not call if dialog_window is already open, this will
create a duplicate without handling the other
if you are unsure if it already exists or not use show_dialog()"""
global dialog_window
dialog_window = tk.Toplevel(root)
label1 = tk.Label(dialog_window,text="this is the dialog window")
label1.pack()
#put other widgets
dialog_window.lift() #ensure it appears above all others, probably will do this anyway
def show_dialog():
"""lifts the dialog_window if it exists or creates a new one otherwise"""
#this can be refactored to only have one call to create_dialog()
#but sometimes extra code will be wanted the first time it is created
if dialog_window is None:
create_dialog()
return
try:
dialog_window.lift()
except tk.TclError:
#window was closed, create a new one.
create_dialog()
root = tk.Tk()
dialog_button = tk.Button(root,
text="show dialog_window",
command=show_dialog)
dialog_button.pack()
root.mainloop()
Op deze manier laat de functie show_dialog
het dialoogvenster zien of het bestaat of niet, merk ook op dat u .winfo_exists()
kunt oproepen om te controleren of het bestaat voordat u probeert het venster op te tillen in plaats van het in een try:except
wikkelen try:except
.
Er is ook de .lower()
-methode die op dezelfde manier werkt als de .lift()
-methode, behalve het venster in de stapel verlagen:
import tkinter as tk #import Tkinter as tk #change to commented for python2
root = tk.Tk()
root.title("ROOT")
extra = tk.Toplevel()
label = tk.Label(extra, text="extra window")
label.pack()
lower_button = tk.Button(root,
text="lower this window",
command=root.lower)
lower_button.pack()
root.mainloop()
U zult merken dat het zelfs onder andere toepassingen verlaagt, om alleen onder een bepaald venster te verlagen, kunt u het doorgeven aan de .lower()
-methode, op dezelfde manier kan dit ook worden gedaan met de .lift()
-methode om alleen een venster boven een ander te openen een.