Python 将对象传递到类实例内的选项卡中

Python 将对象传递到类实例内的选项卡中,python,tkinter,Python,Tkinter,我一直在努力学习OOP。我知道对象可以是类的实例。类具有参数和方法,类似于创建对象的“对象构造函数”。我在我的第一个项目中重新组织代码,以允许任何可能成为类的一部分。现在我正在开发GUI,但在理解使用类构建GUI的过程时遇到了困难。特别是在类中有选项卡,并在每个选项卡中添加对象 下面是我的代码当前外观的示例: import tkinter from tkinter import ttk class Win: def __init__(self, master): n

我一直在努力学习OOP。我知道对象可以是类的实例。类具有参数和方法,类似于创建对象的“对象构造函数”。我在我的第一个项目中重新组织代码,以允许任何可能成为类的一部分。现在我正在开发GUI,但在理解使用类构建GUI的过程时遇到了困难。特别是在类中有选项卡,并在每个选项卡中添加对象

下面是我的代码当前外观的示例:

import tkinter
from tkinter import ttk


class Win:

    def __init__(self, master):
        nb = ttk.Notebook(master, width=390, height=470)
        nb.pack()

        tab = ttk.Frame(nb)
        nb.add(tab, text='title')

        tab2 = ttk.Frame(nb)
        nb.add(tab2, text='Graphs')

        tab3 = ttk.Frame(nb)
        nb.add(tab3, text='Messages')

        tab4 = ttk.Frame(nb)
        nb.add(tab4, text='Instructions')

        label = tkinter.Label(tab, text='text')
        label.grid(row=0, column=0, sticky=tkinter.N, pady=10)

        menu = tkinter.Menu(master, tearoff=False)
        master.config(menu=menu)
        subMenu = tkinter.Menu(menu, tearoff=False)
        menu.add_cascade(label="File", menu=subMenu)
        subMenu.add_separator()
        subMenu.add_command(label='Exit', command=master.destroy)

root = tkinter.Tk()
root.title("SC")
root.geometry('400x500')
root.resizable(width=False, height=False)

main_win = Win(root)

root.mainloop()
要在
main\u win
的每个选项卡中放置对象,我该怎么做?我尝试将对象放在
main\u-win
下面,然后在对象中传递参数
main\u-win
,但这似乎不起作用。我是否应该有一个制作制表符的类,然后创建一个对象
tab
,并将新对象传递到其中


提前谢谢你的帮助。无法在任何地方找到此特定答案。

此代码显示了将内容添加到笔记本选项卡的一种方法。它实现了abarnert的一些建议,以及我自己的一些想法。我已经将笔记本分离到它自己的类中,并将Tk根初始化代码移动到主GUI类中

我并不认为这是做这些事情的最佳方式,我只是举例说明一些可能的方法来启发你

我用
GUI
的不同方法创建笔记本和菜单的大部分工作。我本可以把代码放在
GUI中。uuuu init\uuuu
但是它更模块化,可以在不同的方法中完成,并且它可以阻止
\uuuuuuu init\uuu
方法变得庞大

我已将笔记本和菜单保存为实例属性
self.nb
self.Menu
。这在这里并不是必需的,它们可能只是
GUI的局部变量。但是将它们存储为属性可以从
GUI
的其他方法访问它们,这在向类添加更多内容时可能是必要的


当您从父类派生一个类时,如从
ttk.Notebook
(或从
tk.tk
)派生的
MyNotebook
),如果子类没有自己的
\uuuuu init\uuuuuu
方法,则在创建子实例时将自动调用父类的
\uuuu init\uuuuu
。但是如果子级有自己的
\uuuuu init\uuuu
,则不会自动调用父级
\uuuuuu init\uuuuu
。但是我们需要父级
\uuuu init\uuuu
中的内容来完成我们的新实例
MyNotebook
,以便初始化从
ttk.Notebook
继承的内容。因此,
MyNotebook.\uuuu init\uuu
执行
super
调用以实现这一点

通常,如果子类没有定义父类定义的方法,那么在子实例上调用该方法时,将调用父类的版本。如果子方法确实重新定义了继承的方法,您通常会希望在同一阶段调用子方法内部的父方法,通常使用
super
来执行此操作<代码>\uuuu init\uuuu
有点特殊,因为它通常在创建实例后自动被调用以初始化实例


这里有一个更简单的版本,它不使用子类。它在根窗口上还有一个按钮小部件,当您单击它时,它会打印一个字符串

import tkinter as tk
from tkinter import ttk

class GUI:
    def __init__(self):
        root = tk.Tk()
        root.title("SC")
        root.geometry('400x500')
        root.resizable(width=False, height=False)

        names = ['Title', 'Graphs', 'Messages', 'Instructions']
        self.nb = self.create_notebook(root, names)
        self.menu = self.create_menus(root)

        # We can also add items to the Notebook here
        tab = self.nb.tabs['Instructions']
        tk.Label(tab, text='You should\nread these\ninstructions').pack()

        btn = tk.Button(root, text='Click', command=self.button_command)
        btn.pack()

        root.mainloop()

    def button_command(self):
        print('The button was clicked')

    def create_notebook(self, root, names):
        nb = ttk.Notebook(root, width=390, height=450)
        nb.pack()

        # Create tabs & save them by name in a dictionary
        nb.tabs = {}
        for name in names:
            nb.tabs[name] = tab = ttk.Frame(root)
            nb.add(tab, text=name)

        def add_label(parent, text, row, column):
            label = tk.Label(parent, text=text)
            label.grid(row=row, column=column, sticky=tk.N, pady=10)
            return label

        # Add some labels to each tab
        tab = nb.tabs['Title']
        for i in range(3):
            add_label(tab, 't' + str(i), i, 0)

        tab = nb.tabs['Graphs']
        for i in range(3):
            add_label(tab, 'g' + str(i), 0, i)

        tab = nb.tabs['Messages']
        for i in range(3):
            add_label(tab, 'm' + str(i), i, i)

        return nb

    def create_menus(self, root):
        menu = tk.Menu(root, tearoff=False)
        root.config(menu=menu)
        subMenu = tk.Menu(menu, tearoff=False)
        menu.add_cascade(label="File", menu=subMenu)
        subMenu.add_separator()
        subMenu.add_command(label='Exit', command=root.destroy)
        return menu

GUI()

我尝试将对象放在main_-win下面,然后在对象中传递参数main_-win,但这似乎也不起作用,您确定不希望
win
成为
Frame
的子类,或者仅仅是
笔记本
?事实上,它不是一个真正的窗口,它只是一个创造(然后忘记)窗口的想法。(您可以学习MVC,并将其转换为一个
WinController
类,该类管理
框架
笔记本
,但最好先学习简单的全视图设计,然后让
Win
成为
框架
笔记本
),如果您将其更改为
Win
是一个窗口或其他小部件,那么您可以将
main\u Win
作为父小部件传递给其他小部件,它将正常工作。(我不确定你问的是什么,但我想是的。)很好的解释。
super()。\uuuu init\uuuuu()
意味着什么?@DavidA允许我们访问类的父类,而无需显式命名。因此在
MyNotebook
中,调用
super()。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但我们有理由选择
super
。请参见Python核心开发人员Raymond Hettinger,了解超级计算机惊人的超级能力的精彩介绍。;)另外,我刚刚在我的回答中添加了一些关于
super
和相关事项的信息。这是一个很好的解释。真正让我困惑的一件事是,您的代码似乎多次重复
笔记本
选项卡
。你能解释一下为什么这样写吗?在这段代码中,您是否试图给出几个示例?或者这就是代码的实际外观?@DavidA这只是一个程序,它构建了您的版本所构建的GUI的稍微增强的版本。类和对象并没有那么难,但它可能会让人困惑,而且需要时间才能理解。
import tkinter as tk
from tkinter import ttk

class GUI:
    def __init__(self):
        root = tk.Tk()
        root.title("SC")
        root.geometry('400x500')
        root.resizable(width=False, height=False)

        names = ['Title', 'Graphs', 'Messages', 'Instructions']
        self.nb = self.create_notebook(root, names)
        self.menu = self.create_menus(root)

        # We can also add items to the Notebook here
        tab = self.nb.tabs['Instructions']
        tk.Label(tab, text='You should\nread these\ninstructions').pack()

        btn = tk.Button(root, text='Click', command=self.button_command)
        btn.pack()

        root.mainloop()

    def button_command(self):
        print('The button was clicked')

    def create_notebook(self, root, names):
        nb = ttk.Notebook(root, width=390, height=450)
        nb.pack()

        # Create tabs & save them by name in a dictionary
        nb.tabs = {}
        for name in names:
            nb.tabs[name] = tab = ttk.Frame(root)
            nb.add(tab, text=name)

        def add_label(parent, text, row, column):
            label = tk.Label(parent, text=text)
            label.grid(row=row, column=column, sticky=tk.N, pady=10)
            return label

        # Add some labels to each tab
        tab = nb.tabs['Title']
        for i in range(3):
            add_label(tab, 't' + str(i), i, 0)

        tab = nb.tabs['Graphs']
        for i in range(3):
            add_label(tab, 'g' + str(i), 0, i)

        tab = nb.tabs['Messages']
        for i in range(3):
            add_label(tab, 'm' + str(i), i, i)

        return nb

    def create_menus(self, root):
        menu = tk.Menu(root, tearoff=False)
        root.config(menu=menu)
        subMenu = tk.Menu(menu, tearoff=False)
        menu.add_cascade(label="File", menu=subMenu)
        subMenu.add_separator()
        subMenu.add_command(label='Exit', command=root.destroy)
        return menu

GUI()