tkinter
Несколько окон (виджеты TopLevel)
Поиск…
Разница между Tk и Toplevel
Tk
является абсолютным корнем приложения, это первый виджет, который необходимо создать, и графический интерфейс будет закрыт, когда он будет уничтожен.
Toplevel
- это окно в приложении, закрытие окна уничтожит все дочерние виджеты, размещенные в этом окне {1}, но не выключит программу.
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()
Если ваша программа python представляет только одно приложение (которое почти всегда будет), то у вас должен быть только один экземпляр Tk
, но вы можете создать столько окон Toplevel
сколько хотите.
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}: если Toplevel ( A = Toplevel(root)
) является родителем другого верхнего уровня ( B = Toplevel(A)
), то закрывающее окно A также закрывает окно B.
расположение стека окон (метод .lift)
Самый простой случай, чтобы поднять конкретное окно над другими, просто вызовите метод .lift()
в этом окне (либо Toplevel
либо 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()
Однако, если это окно уничтожено, пытаясь его поднять, это приведет к ошибке:
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"
Часто, когда мы пытаемся поставить конкретное окно перед пользователем, но оно было закрыто, хорошей альтернативой является воссоздание этого окна:
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()
Таким образом, функция show_dialog
покажет диалоговое окно независимо от того, существует оно или нет, также обратите внимание, что вы можете вызвать .winfo_exists()
чтобы проверить, существует ли это, прежде чем пытаться поднять окно, а не обертывать его в try:except
.
Существует также метод .lower()
который работает так же, как метод .lift()
, за исключением опускания окна в стеке:
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()
Вы заметите, что он опускается ниже других приложений, и только ниже ниже определенного окна вы можете передать его .lower()
, аналогичным образом это также можно сделать с помощью .lift()
чтобы только поднять окно над другим один.