我一直在努力学习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_win
中的每个标签中,该怎么办?我尝试将对象放在main_win
下,然后在对象中传递参数main_win
,但这似乎不起作用。我是否应该有一个用于制作标签的类,然后创建一个对象tab
并将新对象传递到其中?
预先感谢您的帮助。无法在任何地方找到此特定答案。
答案 0 :(得分:0)
此代码显示了一种向“笔记本”选项卡添加内容的方法。它实现了abarnert的一些建议以及我自己的一些想法。我将Notebook分离到了自己的类中,并将Tk根初始化代码移到了主GUI类中。
我并不是说这是做这些事情的最好方法,我只是在举例说明一些启发您的可能性。 ;)
import tkinter as tk
from tkinter import ttk
class GUI(tk.Tk):
def __init__(self):
super().__init__()
self.title("SC")
self.geometry('400x500')
self.resizable(width=False, height=False)
names = ['Title', 'Graphs', 'Messages', 'Instructions']
self.nb = self.create_notebook(names)
self.menu = self.create_menus()
# We can also add items to the Notebook here
tab = self.nb.tabs['Instructions']
tk.Label(tab, text='You should\nread these\ninstructions').pack()
self.mainloop()
def create_notebook(self, names):
nb = MyNotebook(self, names)
nb.pack()
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):
menu = tk.Menu(self, tearoff=False)
self.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=self.destroy)
return menu
class MyNotebook(ttk.Notebook):
''' A customised Notebook that remembers its tabs in a dictionary '''
def __init__(self, master, names):
super().__init__(master, width=390, height=470)
# Create tabs & save them by name in a dictionary
self.tabs = {}
for name in names:
self.tabs[name] = tab = ttk.Frame(self)
self.add(tab, text=name)
GUI()
我将以GUI
的不同方法来完成创建笔记本和菜单的大部分工作。我本可以将该代码放在GUI.__init__
中,但是它采用模块化的方式在单独的方法中执行,因此可以阻止.__init__
方法变大。
我已将“笔记本和菜单”另存为实例属性self.nb
和self.menu
。这里并不是必须的,它们可以只是GUI.__init__
的局部变量,例如nb
和menus
。但是,将它们存储为属性可以使它们从GUI
的其他方法访问,当您向类中添加更多内容时,这可能是必需的。
如果您从父类派生一个类,例如子类没有,则从MyNotebook
来的ttk.Notebook
(或从GUI
来的tk.Tk
) 具有自己的__init__
方法,那么当您创建子实例时,父级的__init__
将自动被调用。但是,如果孩子有自己的__init__
,则父__init__
不会被自动呼叫。但是我们需要父__init__
中的内容来完成MyNotebook
的新实例,以便初始化从ttk.Notebook
继承的内容。因此,MyNotebook.__init__
进行了super
调用来实现这一目标。
通常,如果子类未定义父类定义的方法,则在子实例上调用该方法时,将调用父类的版本。而且,如果子级确实重新定义了继承的方法,您通常会希望在同一阶段在子级方法内调用父级方法,通常使用super
来做到这一点。 __init__
有点特殊,因为通常在创建实例后会自动调用它来初始化实例。
这是一个不使用子类的简单版本。它在根窗口上还具有一个Button小部件,当您单击它时会打印一个字符串。
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()