Блокнот Python tkinter как метод в классе

Это проблема с созданием записной книжки 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()

Вам нужно вызвать функцию макета в экземпляре класса Stakeholders для вашего второго кода.

acw1668 24.05.2024 01:28

Разве .pack() не макет, где идет каждый Frame и Notebook?

David Collins 24.05.2024 01:34

Во втором примере блокнот создается как дочерний элемент Stakeholder, но экземпляр Stakeholder невидим, поскольку в нем не вызывается никакая функция макета.

acw1668 24.05.2024 02:05

Почему блокнот создан в детстве Stakeholder? Он создается в методе класса. Это не подкласс или дочерний класс.

David Collins 24.05.2024 02:21

Посмотрите внимательно на свои коды. В первом примере родительским элементом записной книжки является self.master, но во втором примере он есть self.

acw1668 24.05.2024 02:46

В первом вопросе, на который я дал ссылку (выше), решение было изменено с self.master на self. На самом деле, вы предложили это решение. Почему это по-другому?

David Collins 24.05.2024 02:54
self.master является родителем self. Это другое.
acw1668 24.05.2024 03:03

Обратите также внимание, что две строки frame1.pack(...) и frame2.pack(...) вообще не нужны.

acw1668 24.05.2024 14:02
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
8
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы были очень близки, но нужно несколько незначительных изменений

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()
  1. Обычно вы хотите, чтобы ваши виджеты были дочерними элементами класса, в котором они находятся (т. е. master=self), а не дочерними элементами родительского класса этого класса (т. е. master=self.master).

  2. Вызов менеджера макетов (например, pack, grid или place) на вашем экземпляре Stakeholders был настоящим недостающим элементом — именно это добавляет его в пользовательский интерфейс.

    2а. Обратите внимание, что вы также можете использовать Stakeholders(root).pack(...). Но было бы неплохо выработать привычку создавать экземпляры виджетов отдельно от управления макетом, потому что pack, grid и place все возвращают None. Это означает, что когда вы делаете что-то вроде stakeholders = Stakeholders(root).pack(), stakeholders оценивается как None (а не ваш виджет!), что может вызвать головную боль в дальнейшем, если вы не будете осторожны.

2а действительно хороший совет. Я этого не осознавал. Спасибо. Я заметил, что вы удалили метод def make_notebook(self) и поместили его содержимое в __init__. Почему это? Какая польза от этого шага?

David Collins 24.05.2024 22:41

@DavidCollins это сбивает с толку многих людей, заходящих в tkinter, поэтому я решил, что об этом стоит упомянуть! Кроме того, большая часть этого кода взята из вашего первого примера, поэтому я просто работал с ним.

JRiggles 25.05.2024 03:49

Другие вопросы по теме