Это проблема с созданием записной книжки tkinter в методе класса.
Этот вопрос решается удалением master, что не является моей проблемой: Python Tkinter — Как добавить класс блокнота в tk.toplevel?.
Этот вопрос касается добавления изображений, и он не имеет такой же структуры (из которой я мог бы сделать вывод о решении): Виджет Python Tkinter Notebook.
Когда я создаю блокнот из __init__, блокнот открывается нормально.
import tkinter as tk
from tkinter import ttk
class Stakeholders(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
notebook = ttk.Notebook(self.master)
notebook.pack(pady=10, expand=True)
# create frames
frame1 = ttk.Frame(notebook, width=400, height=280)
frame2 = ttk.Frame(notebook, width=400, height=280)
frame1.pack(fill='both', expand=True)
frame2.pack(fill='both', expand=True)
# add frames to notebook
notebook.add(frame1, text='Tab 1')
notebook.add(frame2, text='Tab 2')
def create_window():
root = tk.Tk()
root.geometry('400x300')
root.title('Stakeholders')
Stakeholders(root)
root.mainloop()
if __name__ == "__main__":
create_window()
Когда я помещаю блокнот в метод класса, окно открывается, но нет ни блокнота, ни вкладок.
import tkinter as tk
from tkinter import ttk
class Stakeholders(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.make_notebook()
def make_notebook(self):
self.notebook = ttk.Notebook(self)
self.notebook.pack(pady=10, expand=True)
frame1 = ttk.Frame(self.notebook, width=300, height=300)
frame2 = ttk.Frame(self.notebook, width=300, height=300)
frame1.pack(fill='both', expand=True)
frame2.pack(fill='both', expand=True)
self.notebook.add(frame1, text='Owner')
self.notebook.add(frame2, text='Architect')
def create_window():
root = tk.Tk()
root.geometry('400x300')
root.title('Stakeholders')
Stakeholders(root)
root.mainloop()
if __name__ == "__main__":
create_window()
Разве .pack() не макет, где идет каждый Frame и Notebook?
Во втором примере блокнот создается как дочерний элемент Stakeholder, но экземпляр Stakeholder невидим, поскольку в нем не вызывается никакая функция макета.
Почему блокнот создан в детстве Stakeholder? Он создается в методе класса. Это не подкласс или дочерний класс.
Посмотрите внимательно на свои коды. В первом примере родительским элементом записной книжки является self.master, но во втором примере он есть self.
В первом вопросе, на который я дал ссылку (выше), решение было изменено с self.master на self. На самом деле, вы предложили это решение. Почему это по-другому?
self.master является родителем self. Это другое.
Обратите также внимание, что две строки frame1.pack(...) и frame2.pack(...) вообще не нужны.






Вы были очень близки, но нужно несколько незначительных изменений
import tkinter as tk
from tkinter import ttk
class Stakeholders(tk.Frame):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
notebook = ttk.Notebook(self) # you want 'self' here, not self.master
notebook.pack(pady=10, expand=True)
# create frames
frame1 = ttk.Frame(notebook, width=400, height=280)
frame2 = ttk.Frame(notebook, width=400, height=280)
frame1.pack(fill='both', expand=True)
frame2.pack(fill='both', expand=True)
# add frames to notebook
notebook.add(frame1, text='Tab 1')
notebook.add(frame2, text='Tab 2')
def create_window() -> None:
root = tk.Tk()
root.geometry('400x300')
root.title('Stakeholders')
# instantiate your Stakeholders class
stakeholders = Stakeholders(root)
# add it to the UI via 'pack' or another layout manager (I tend to prefer pack)
stakeholders.pack(expand=True, fill='both')
root.mainloop()
if __name__ == "__main__":
create_window()
Обычно вы хотите, чтобы ваши виджеты были дочерними элементами класса, в котором они находятся (т. е. master=self), а не дочерними элементами родительского класса этого класса (т. е. master=self.master).
Вызов менеджера макетов (например, pack, grid или place) на вашем экземпляре Stakeholders был настоящим недостающим элементом — именно это добавляет его в пользовательский интерфейс.
2а. Обратите внимание, что вы также можете использовать Stakeholders(root).pack(...). Но было бы неплохо выработать привычку создавать экземпляры виджетов отдельно от управления макетом, потому что pack, grid и place все возвращают None. Это означает, что когда вы делаете что-то вроде stakeholders = Stakeholders(root).pack(), stakeholders оценивается как None (а не ваш виджет!), что может вызвать головную боль в дальнейшем, если вы не будете осторожны.
2а действительно хороший совет. Я этого не осознавал. Спасибо. Я заметил, что вы удалили метод def make_notebook(self) и поместили его содержимое в __init__. Почему это? Какая польза от этого шага?
@DavidCollins это сбивает с толку многих людей, заходящих в tkinter, поэтому я решил, что об этом стоит упомянуть! Кроме того, большая часть этого кода взята из вашего первого примера, поэтому я просто работал с ним.
Вам нужно вызвать функцию макета в экземпляре класса
Stakeholdersдля вашего второго кода.