Python 创建从一个类到另一个类的变量

Python 创建从一个类到另一个类的变量,python,python-3.x,class,Python,Python 3.x,Class,我目前正在与tkinter一起完成一项学校作业,为用户创建一个图形用户界面以输入他们的输入。我决定将输入分成不同的页面,以避免用户被问题淹没,并且不需要滚动 每一页都有一系列的标签和条目,在一个右除数和一个左除数上分开,我通过一些努力设法在每一页上实现了这一点。这是我工作代码的简化版本: import tkinter as tk class Layers(tk.Frame): def __init__(self, root): super().__init__(roo

我目前正在与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_左侧和container_右侧使用内部填充
  • 为每个页面设置容器是多余的,因为它们都将被拆分为两个框架。我尝试了以下方法,但没有达到预期效果(一点也没有)
类层(tk.Frame): 定义初始化(自,根): 超级() self.layers=[] self.layers.append(欢迎页面(self)) self.layers.append(表单_1(self)) self.layers.append(表单_2(self)) 对于self.layers中的层: 图层添加表单(自) 图层。添加按钮(自) layer.grid(行=0,列=0,sticky=“nsew”) layer.container_left=tk.Frame(layer,background=“#BAFFCE”) layer.container_right=tk.Frame(layer,background=“#72FF9A”) layer.container\u left.grid(行=0,列=0,sticky=“nsew”) layer.container\u right.grid(行=0,列=1,sticky=“nsew”) layer.grid\u columnconfigure(0,权重=1,uniform=“group1”) layer.grid\u columnconfigure(1,权重=1,uniform=“group1”) layer.grid_rowconfigure(0,权重=1) 打印(图层) self.layers[0].tkraise() 我得到的错误是
AttributeError:“Form\u 1”对象没有属性“container\u right”
。我从中得到的是,我没有在类中创建变量,而是在其他地方创建变量,即使我使用的是
层。
。如何在不重用代码的情况下在类内部创建变量


我对Python和Tkinter还不太熟悉,因此也非常感谢您提出的任何其他建议。

您可以通过将第17行更改为以下内容,在第一段代码中看到
ipadx
ipady
的效果:

layer.grid(row=0, column=0, sticky="nsew", ipadx=30, ipady=30,)

我知道您提到希望保持类结构不变,但为表单页面引入超类可能是值得的。从那里,您可以定义
add_form
add_按钮
实例方法,只需从超类的
\uuuuu init\uuuu
内部调用它们,而不必在页面中循环。比如说:

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_按钮
add_表单
方法。 然后,对于特定表单,您可以执行以下操作:

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\u left
container\u right
属性。 然后,如果某些表单需要更多按钮,您可以在该表单的类中重写方法
add\u buttons
。对于任何其他方法也是如此。 然后,您只需要一个地方来存储所有页面,比如
类。在我看来,你不需要把所有的图层都放在一个网格上,因为你将从导航按钮调用
tkraise
。我认为您的
类可以缩减为:

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()
一般来说,继承层次结构是减少代码重复的好方法。希望这有帮助:)

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()