创建从一个类到另一个类的变量
Posted
技术标签:
【中文标题】创建从一个类到另一个类的变量【英文标题】:Creating a variable from one class to another 【发布时间】:2019-05-28 02:32:05 【问题描述】:我目前正在与 tkinter 合作完成学校作业,为用户创建一个图形用户界面以输入他们的输入。我决定将输入拆分到不同的页面中,以免用户被问题淹没,也不需要滚动。 每个页面都有一系列标签和条目,分别在一个左右除数上,我以某种方式设法让它在每个页面上工作,并付出了一些努力。这是我的工作代码的简化版本:
import tkinter as tk
class Layers(tk.Frame):
def __init__(self, root):
super().__init__(root)
self.layers = []
self.layers.append(Welcome_Page(self))
self.layers.append(Form_1(self))
self.layers.append(Form_2(self))
for layer in self.layers:
layer.add_form(self)
layer.add_buttons(self)
layer.grid(row=0, column=0, sticky="nsew")
self.layers[0].tkraise()
class Welcome_Page(tk.Frame):
def __init__(self, root):
super().__init__(root, width=600, height=800, background="red")
def add_buttons(self, root):
self.next = tk.Button(self, text="Next page", width=25, height=5, command=self.master.layers[1].tkraise)
self.next.place(relx=1, rely=1, anchor="se")
self.prev = tk.Button(self, text="Quit", width=25, height=5, command=self.master.master.destroy)
self.prev.place(relx=0, rely=1, anchor="sw")
pass
def add_form(self, root):
self.text_label = tk.Label(self, text="Welcome to this program")
self.text_label.place(relx=0.5, rely=0, anchor="n")
pass
class Form_1(tk.Frame):
def __init__(self, root):
super().__init__(root, width=600, height=800, background="yellow")
def add_buttons(self, root):
self.next = tk.Button(self, text="Next page", width=25, height=5, command=self.master.layers[2].tkraise)
self.next.place(relx=1, rely=1, anchor="se")
self.prev = tk.Button(self, text="Back", width=25, height=5, command=self.master.layers[0].tkraise)
self.prev.place(relx=0, rely=1, anchor="sw")
pass
def add_form(self, root):
self.text_label = tk.Label(self, text="Personal data")
self.text_label.place(relx=0.5, rely=0, anchor="n")
self.container_left = tk.Frame(self, background="#BAFFCE")
self.container_right = tk.Frame(self, background="#72FF9A")
self.container_left.grid(row=0, column=0, sticky="nsew")
self.container_right.grid(row=0, column=1, sticky="nsew")
self.grid_columnconfigure(0, weight=1, uniform="group1")
self.grid_columnconfigure(1, weight=1, uniform="group1")
self.grid_rowconfigure(0, weight=1)
self.last_name_label = tk.Label(self.container_right, text="Last name")
self.last_name_space = tk.Entry(self.container_right, text="lastname")
self.last_name_label.grid(row=0, column=0, padx=(10,0), pady=(10,0))
self.last_name_space.grid(row=0, column=1, padx=(5, 0), pady=(10,0))
pass
class Form_2(tk.Frame):
def __init__(self, root):
super().__init__(root, width=600, height=800, background="gray")
def add_buttons(self, root):
self.next = tk.Button(self, text="Next page", width=25, height=5)
self.next.place(relx=1, rely=1, anchor="se")
self.prev = tk.Button(self, text="Back", width=25, height=5, command=self.master.layers[1].tkraise)
self.prev.place(relx=0, rely=1, anchor="sw")
pass
def add_form(self, root):
self.text_label = tk.Label(self, text="Third page")
self.text_label.place(relx=0.5, rely=0, anchor="n")
pass
if __name__ == '__main__':
root = tk.Tk()
root.geometry("600x800")
window = Layers(root)
window.pack(expand=True, fill="both")
root.mainloop()
尽管如此,在将每个页面拆分为两个不同的 Frame() 容器时,我偶然发现了两个问题:
用 ipadx 和 ipady 设置框架的内部填充似乎没有任何作用。不过,我已经使用 padx 和 pady 手动将其中的每个元素设置在其位置,这工作正常,但我相信我应该能够在 container_left 和 container_right 上使用内部填充来代替。 为每个页面设置容器是多余的,因为它们都将被分成两个框架。我尝试了以下方法,但它没有按我的预期工作(根本没有)。 类层(tk.Frame): def __init__(self, root): 超级().__init__(根) self.layers = [] self.layers.append(Welcome_Page(self)) self.layers.append(Form_1(self)) self.layers.append(Form_2(self)) 对于 self.layers 中的层: layer.add_form(self) layer.add_buttons(self) layer.grid(row=0, column=0, sticky="nsew") layer.container_left = tk.Frame(layer, background="#BAFFCE") layer.container_right = tk.Frame(layer, background="#72FF9A") layer.container_left.grid(row=0, column=0, sticky="nsew") layer.container_right.grid(row=0, column=1, sticky="nsew") layer.grid_columnconfigure(0, weight=1, uniform="group1") layer.grid_columnconfigure(1, weight=1, uniform="group1") layer.grid_rowconfigure(0, weight=1) 打印(层) self.layers[0].tkraise()我得到的错误是AttributeError: 'Form_1' object has no attribute 'container_right'
。我从中得到的是,我没有在类中创建变量,而是在其他地方创建了变量,即使我使用的是layer.
。如何在不重用代码的情况下在类中创建变量?
也欢迎任何其他建议,因为我对 Python 和 Tkinter 还很陌生。
【问题讨论】:
【参考方案1】:你可以在你的第一个代码中看到ipadx
和ipady
的效果,将第17行改为:
layer.grid(row=0, column=0, sticky="nsew", ipadx=30, ipady=30,)
【讨论】:
【参考方案2】:我知道您提到希望保持类结构不变,但为您的表单页面引入超类可能是值得的。从那里,您可以定义add_form
和add_buttons
实例方法,并在内部从超类的__init__
调用它们,而不是循环浏览页面。所以,比如:
class FormPage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, width=600, height=800, background="yellow")
self.parent=parent
self.add_buttons()
self.add_form()
def add_buttons(self):
self.next = tk.Button(self, text="Next page", width=25, height=5)
self.next.place(relx=1, rely=1, anchor="se")
self.prev = tk.Button(self, text="Back", width=25, height=5)
self.prev.place(relx=0, rely=1, anchor="sw")
def add_form(self):
self.text_label = tk.Label(self) #use the configure method in child classes to set the text
self.text_label.place(relx=0.5, rely=0, anchor="n")
self.container_left = tk.Frame(self, background="#BAFFCE")
self.container_right = tk.Frame(self, background="#72FF9A")
self.container_left.grid(row=0, column=0, sticky="nsew")
self.container_right.grid(row=0, column=1, sticky="nsew")
self.grid_columnconfigure(0, weight=1, uniform="group1")
self.grid_columnconfigure(1, weight=1, uniform="group1")
self.grid_rowconfigure(0, weight=1)
所以,FormPage
的初始化将在表单页面被实例化时自动调用add_buttons
和add_form
方法。
然后对于一个特定的形式,你可以这样做:
class Form_1(FormPage):
def __init__(self, parent):
tk.Frame.__init__(parent) #call FormPage's initialisation
def add_buttons(self):
self.next.configure(command=self.parent.layers[1].tkraise)
...#add the specific functionality of the buttons using configure
def add_form(self):
super().add_form()
self.text_Label.configure(text="Personal Information")
self.last_name_label = tk.Label(self.container_right, text="Last name")
self.last_name_space = tk.Entry(self.container_right, text="lastname")
self.last_name_label.grid(row=0, column=0, padx=(10,0), pady=(10,0))
self.last_name_space.grid(row=0, column=1, padx=(5, 0), pady=(10,0))
因此,FormPage
的任何子级都具有属性container_left
和container_right
。
然后,如果某些表单需要更多按钮,您可以重写该表单类中的方法add_buttons
。对于任何其他方法也是如此。
然后,您只需要一个地方来存储您的所有页面,例如您的 Layers
类。 IMO,您不需要将所有图层都放在网格上,因为无论如何您都会从导航按钮调用tkraise
。我认为您的 Layers
课程可以简化为:
class Layers(tk.Tk):
def __init__(self):
super().__init__(self)
self.layers = []
for F in Welcome_Page, Form_1, Form_2:
self.layers.append(F(self))
self.layers[0].tkraise()
一般来说,继承层次结构是减少代码重复的好方法。希望这会有所帮助:)
【讨论】:
以上是关于创建从一个类到另一个类的变量的主要内容,如果未能解决你的问题,请参考以下文章
jQuery选择从一个类到另一个类的元素。一切都在同一水平上 Title 1