В настоящее время у меня есть две проблемы с экземплярами Toplevel в Tkinter.

Первое и самое важное: я хочу отобразить всплывающее окно и поместить в него 2 кадра для лучшего расположения в сетке, но это не сработает, поскольку я ожидаю, что оно будет работать:

import tkinter


root = tkinter.Tk()
tkinter.Button(root, text="ABC").grid(column=0, row=0)
tkinter.Label(root, text="FOO").grid(column=1, row=1)

win = tkinter.Toplevel()
f1 = tkinter.Frame(win).grid(row=0, column=0)
f2 = tkinter.Frame(win).grid(row=1, column=1)
tkinter.Label(f1, text="FRAME 1").grid()
tkinter.Label(f2, text="FRAME 2").grid()

root.mainloop()

Я ожидаю, что «FRAME 1» и «FRAME 2» будут размещены в окне Toplevel, но они фактически размещены в root. Как я могу это исправить?

Во-вторых, менее важно: всплывающее окно в приведенном выше коде появляется за корневым окном, в то время как я хотел бы, чтобы оно располагалось перед root, как мне этого добиться?

1
AracKnight 23 Окт 2018 в 16:24

2 ответа

Лучший ответ

При настройке вашего менеджера геометрии, будь то grid(), pack() или place(), и вам необходимо иметь возможность взаимодействовать с этим виджетом позже, вам нужно будет присвоить виджет переменной, а затем применить менеджер геометрии на новой строке, используя имя этой переменной. Таким образом, ваша переменная будет не значением None, а верным виджетом. Это происходит потому, что все менеджеры геометрии возвращают None.

Следующая причина, по которой ваши метки находятся в неправильных окнах, заключается в том, что когда ваши метки пытаются соединиться с f1 и f2, они не могут найти правильный контейнер tkinter из-за значений None таким образом, по умолчанию используется корневое окно tkinter при попытке разместить его на чем-либо.

Исправив проблемы None, вы также исправите проблему с ярлыком.

Чтобы решить вопрос о том, что ваше окно верхнего уровня не находится перед вашим корневым окном, есть несколько вещей, которые вы можете сделать. Основная причина, по которой это происходит, заключается в том, что ваш код генерирует верхний уровень на __init__, а не позже с помощью кнопки или события по времени.

Если вам действительно нужно, чтобы ваше окно верхнего уровня открывалось одновременно с root, вы можете использовать after() и функцию для этого, и оно будет размещено сверху. Если вам не нужно это прямо при открытии окна, вы можете назначить команду кнопке для запуска функции, которая строит верхнее окно.

Вот пример с after():

import tkinter as tk


root = tk.Tk()

def create_top():
    win = tk.Toplevel(root)
    f1 = tk.Frame(win)
    f1.grid(row=0, column=0)
    f2 = tk.Frame(win)
    f2.grid(row=1, column=1)
    tk.Label(f1, text="FRAME 1").grid()
    tk.Label(f2, text="FRAME 2").grid()

tk.Button(root, text="ABC").grid(column=0, row=0)
tk.Label(root, text="FOO").grid(column=1, row=1)

root.after(10, create_top)
root.mainloop()

Вот пример с кнопкой:

import tkinter as tk


root = tk.Tk()

def create_top():
    win = tk.Toplevel(root)
    f1 = tk.Frame(win)
    f1.grid(row=0, column=0)
    f2 = tk.Frame(win)
    f2.grid(row=1, column=1)
    tk.Label(f1, text="FRAME 1").grid()
    tk.Label(f2, text="FRAME 2").grid()

tk.Button(root, text="ABC", command=create_top).grid(column=0, row=0)
tk.Label(root, text="FOO").grid(column=1, row=1)

root.mainloop()
2
Mike - SMT 23 Окт 2018 в 14:04

Вы устанавливаете свои кадры f1 и f2 на возвращаемое значение команды grid(), которое равно None, поэтому tkinter.Label(f1, text="FRAME 1").grid() не работает так, как вы ожидаете.

Попробуйте что-то вроде этого:

win = tkinter.Toplevel()
f1 = tkinter.Frame(win)
f1.grid(row=0, column=0)
tkinter.Label(f1, text="FRAME 1").grid()
2
user10455554 23 Окт 2018 в 13:37
52950267