Вопрос или проблема
Пытаюсь понять, как указать, какое окно будет содержать какой виджет. У меня возникают трудности с чем-то, что кажется невероятно простым, но я не могу этого понять. Следующее из Википедии (https://en.wikipedia.org/wiki/Tkinter):
import tkinter as tk
class Application(tk.Frame):
def __init__(self, root=None):
tk.Frame.__init__(self, root)
self.grid()
self.createWidgets()
def createWidgets(self):
self.medialLabel = tk.Label(self, text="Hello World")
self.medialLabel.config(bg="#00ffff")
self.medialLabel.grid()
self.quitButton = tk.Button(self, text="Quit", command=self.quit)
self.quitButton.grid()
app = Application()
app.root = tk.Tk()
app.root.title('Sample application')
app.mainloop()
Мои вопросы: Почему всплывают 2 окна? Как мне переписать это, чтобы виджеты отображались в окне «Sample application»? Как я мог бы изменить это, чтобы показать метку в одном окне и кнопку в другом, используя ООП?
Я исключил «root» из кода: никаких изменений в выводе. Исключение self.grid() показывает 2 пустых окна, как и исключение функции и перемещение метки и кнопки в основной код. Похоже, что tk.Frame ничего не делает.
Ответ или решение
Для решения проблемы с виджетами в Tkinter и их размещением в окне с использованием объектно-ориентированного программирования (ООП) важно понимать, как правильно использовать классы и иерархию виджетов в Tkinter.
1. Понимание структуры приложения
Ваш исходный код создает два окна, потому что объект Application
создается до того, как вы инициализируете основной корневой виджет (tk.Tk()
). Таким образом, self
(который представляет экземпляр класса Application
) не имеет родителя, что приводит к созданию второго окна.
2. Исправление кода
Чтобы избежать появления двух окон и разместить все виджеты в одном, создайте объект tk.Tk()
перед инициализацией класса Application
, передав его как аргумент:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, root=None):
tk.Frame.__init__(self, root)
self.grid()
self.createWidgets()
def createWidgets(self):
self.medialLabel = tk.Label(self, text="Hello World", bg="#00ffff")
self.medialLabel.grid()
self.quitButton = tk.Button(self, text="Quit", command=self.quit)
self.quitButton.grid()
app = Application(tk.Tk()) # Прямо создаем экземпляр Tk и передаем его
app.root = app # Устанавливаем root в это же приложение
app.root.title('Sample application')
app.mainloop()
3. Размещение виджетов в разных окнах
Если ваша цель — отобразить метку в одном окне и кнопку в другом, вы можете создать вспомогательные фреймы и разместить их в отдельных окнах. Например:
import tkinter as tk
class LabelFrame(tk.Toplevel):
def __init__(self):
super().__init__()
self.title("Label Window")
self.label = tk.Label(self, text="Hello World", bg="#00ffff")
self.label.pack()
class ButtonFrame(tk.Toplevel):
def __init__(self):
super().__init__()
self.title("Button Window")
self.quitButton = tk.Button(self, text="Quit", command=self.quit)
self.quitButton.pack()
app = tk.Tk()
app.title('Sample application')
label_window = LabelFrame()
button_window = ButtonFrame()
app.mainloop()
4. Объяснение структуры
В этом новом коде:
- Мы создаем два отдельных класса
LabelFrame
иButtonFrame
, которые наследуются отtk.Toplevel
. Это позволяет открывать новое окно для каждого фрейма. - Метод
super().__init__()
инициализирует родительский класс, что обеспечивает правильное создание виджетов. pack()
используется для расположения метки и кнопки внутри их соответствующих окон.
Заключение
Используя указанные подходы, вы можете организовать ваши виджеты таким образом, чтобы они отображались в нужных окнах и соответствовали требованиям вашей программы. Это является основой для построения более сложных приложений на Tkinter. Понимание иерархии виджетов, а также принципов ООП поможет вам справляться с более сложными задачами в разработке графических интерфейсов.