简体   繁体   English

Python 类 - 从父类继承属性到顶层

[英]Python class - inherit attribute from parent class to toplevel

I am trying to use OOP approach to create class that inherit from Parent class to top-level.我正在尝试使用 OOP 方法来创建从父类继承到顶级的类。 I want to get the self.txtofName from Window1 to Window2 class.我想从Window1Window2类获取self.txtofName But it raises an "AttributeError: type object 'Window1' has no attribute 'txtofName'".但它引发了“AttributeError:类型对象'Window1'没有属性'txtofName'”。 Can anyone help me?谁能帮我?

from tkinter import *
from PIL import Image, ImageTk
import time
from tkinter import ttk

class Window1(object):
    def __init__(self, master):
        self.master = master
        self.master.geometry = ('1600x750+0+0')
        self.master.config(bg='powder blue')
        self.master.title('ALVO HOTEL')
        
        # ==========Framing============
        self.ftop = Frame(master, width=1600, height=100, bg='powder blue', relief=RIDGE, pady=20)
        self.ftop.grid(columnspan=3, column=0, row=0)
        self.f1 = Frame(master,width=800,height=700,relief=SUNKEN, bg='powder blue', pady=50, bd=3)
        self.f1.grid(column=1, row=2, sticky="nsew")
        self.f4 = Frame(master, width=100, height=700, relief=SUNKEN, bg='powder blue', pady=50, padx=20, bd=3)
        self.f4.grid(column=2, row=2, sticky="nsew")


        self.labelofName = Label(self.f1, font=('arial', 16, 'bold'), text='Name: ', bg='powder blue', bd=10, anchor=W)
        self.labelofName.grid(row=0, column=0, pady=(20, 10))
        self.txtofName = Entry(self.f1, font=('arial', 16, 'bold'), bd=10, insertwidth=4, bg='white', justify='left')
        self.txtofName.grid(row=0, column=1, pady=(20, 10))

        self.btnNext = Button(self.f1, padx=10, pady=8, bd=10, fg='white', font=('arial', 10, 'bold'), width=10, text='Next Page', bg='green', command=self.new_window_pop)
        self.btnNext.grid(row=6, column=1, sticky=E)
        
    def new_window_pop(self):
        Window2(Toplevel(self.master))


class Window2(Window1):
    def __init__(self, master):
        self.master = master
        self.master.geometry = ('1350x750+0+0')
        self.master.config(bg='powder blue')
        self.master.title('User Information and Payment')

        self.ftitle = Frame(master, bd=10, width=1350, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle.grid(columnspan=3, column=0, row=0)
        self.ftitle2 = Frame(master, bd=10, width=1350, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle2.grid(columnspan=3, column=0, row=3, pady=(0,20))
        self.fbutton = Frame(master, width=1350, height=50, bg='powder blue', relief=RIDGE, padx=10, pady=20)
        self.fbutton.grid(columnspan=3, column=0, row=2)
        self.finfomain = Frame(master, bd=10, width=1350, height=400, bg='powder blue', relief=RIDGE)
        self.finfomain.grid(columnspan=3, column=0, row=1)

        self.finfo1 = Frame(self.finfomain, bd=5, width=900, height=300, bg='powder blue', relief=RIDGE, padx=10)
        self.finfo1.grid(column=0, row=0)
        self.finfo1a = Frame(self.finfomain, bd=5, width=900, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo1a.grid(column=0, row=1)
        self.finfo2 = Frame(self.finfomain, bd=5, width=450, height=400, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo2.grid(column=1, row=0, rowspan=2)

        name = Window1.txtofName.get()
        self.FirstName = StringVar()

        self.lblfirstname = Label(self.finfo1, font=('arial', 16, 'bold'), bg='powderblue', text='First Name:', padx=2)
        self.lblfirstname.grid(row=0, column=0, sticky=W)
        self.txtfirstfname = Entry(self.finfo1, font=('arial', 16, 'bold'), textvariable=self.FirstName, bd=3, insertwidth=5, bg='white', justify='left')
        self.txtfirstfname.grid(row=0, column=1)
        
def main():
    root = Tk()
    app = Window1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Full traceback:完整追溯:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python\Python385\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "d:/Code/Cpet5/new.py", line 31, in new_window_pop
    Window2(Toplevel(self.master))
  File "d:/Code/Cpet5/new.py", line 57, in __init__
    name = Window1.txtofName.get()
AttributeError: type object 'Window1' has no attribute 'txtofName'

Follow these steps按着这些次序

Don't do app = Window1(root) Because you already inherited Window1 in Window2不要做app = Window1(root)因为你已经继承了 Window2 中的 Window1

So, use super to initialize in Window2所以,在Window2中使用super来初始化

super().__init__(master)

Now you can do anythong for Window1 so, Assign command for button self.btnNext.config(command=self.new_window_pop)现在你可以为 Window1 做任何事情,为按钮self.btnNext.config(command=self.new_window_pop)分配命令

Now create a method for TopLevel Window:现在为 TopLevel Window 创建一个方法:

Here is your full code:这是您的完整代码:

from tkinter import *
from PIL import Image, ImageTk
import time
from tkinter import ttk


class Window1(object):
    def __init__(self, master):
        self.master = master
        self.master.geometry = ('1600x750+0+0')
        self.master.config(bg='powder blue')
        self.master.title('ALVO HOTEL')

        # ==========Framing============
        self.ftop = Frame(master, width=1600, height=100, bg='powder blue', relief=RIDGE, pady=20)
        self.ftop.grid(columnspan=3, column=0, row=0)
        self.f1 = Frame(master, width=800, height=700, relief=SUNKEN, bg='powder blue', pady=50, bd=3)
        self.f1.grid(column=1, row=2, sticky="nsew")
        self.f4 = Frame(master, width=100, height=700, relief=SUNKEN, bg='powder blue', pady=50, padx=20, bd=3)
        self.f4.grid(column=2, row=2, sticky="nsew")

        self.labelofName = Label(self.f1, font=('arial', 16, 'bold'), text='Name: ', bg='powder blue', bd=10, anchor=W)
        self.labelofName.grid(row=0, column=0, pady=(20, 10))
        self.txtofName = Entry(self.f1, font=('arial', 16, 'bold'), bd=10, insertwidth=4, bg='white', justify='left')
        self.txtofName.grid(row=0, column=1, pady=(20, 10))

        self.btnNext = Button(self.f1, padx=10, pady=8, bd=10, fg='white', font=('arial', 10, 'bold'), width=10,
                              text='Next Page', bg='green')
        self.btnNext.grid(row=6, column=1, sticky=E)


class Window2(Window1):
    def __init__(self, master):
        super().__init__(master)
        self.btnNext.config(command=self.new_window_pop)

    def new_window_pop(self):
        self.master = Toplevel(self.master)
        self.master.geometry = '1350x750+0+0'
        self.master.config(bg='powder blue')
        self.master.title('User Information and Payment')

        self.ftitle = Frame(self.master, bd=10, width=1350, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle.grid(columnspan=3, column=0, row=0)
        self.ftitle2 = Frame(self.master, bd=10, width=1350, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle2.grid(columnspan=3, column=0, row=3, pady=(0, 20))
        self.fbutton = Frame(self.master, width=1350, height=50, bg='powder blue', relief=RIDGE, padx=10, pady=20)
        self.fbutton.grid(columnspan=3, column=0, row=2)
        self.finfomain = Frame(self.master, bd=10, width=1350, height=400, bg='powder blue', relief=RIDGE)
        self.finfomain.grid(columnspan=3, column=0, row=1)

        self.finfo1 = Frame(self.finfomain, bd=5, width=900, height=300, bg='powder blue', relief=RIDGE, padx=10)
        self.finfo1.grid(column=0, row=0)
        self.finfo1a = Frame(self.finfomain, bd=5, width=900, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo1a.grid(column=0, row=1)
        self.finfo2 = Frame(self.finfomain, bd=5, width=450, height=400, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo2.grid(column=1, row=0, rowspan=2)

        name = self.txtofName.get()
        self.FirstName = StringVar()

        self.lblfirstname = Label(self.finfo1, font=('arial', 16, 'bold'), bg='powderblue', text='First Name:', padx=2)
        self.lblfirstname.grid(row=0, column=0, sticky=W)
        self.txtfirstfname = Entry(self.finfo1, font=('arial', 16, 'bold'), textvariable=self.FirstName, bd=3,
                                   insertwidth=5, bg='white', justify='left')
        self.txtfirstfname.grid(row=0, column=1)


def main():
    root = Tk()
    app = Window2(root)
    root.mainloop()


if __name__ == '__main__':
    main()

If you need any explanation ask in comment.如果您需要任何解释,请在评论中询问。

hi james I think that the problem is that that you're wrong to let the Windows2 class inherit the Windows1 class.嗨,詹姆斯,我认为问题在于让 Windows2 类继承 Windows1 类是错误的。 I've made some changes like我做了一些改变,比如

def new_window_pop(self):
        #avoid declaring the class type here
        #Window2(Toplevel(self.master))
        #and pass self because you can thought to self as master...
        Window2(self)

and in the windows2 notice that we declare geometry, config, title as self, here self is the new windows, and self.parent is window1在windows2中注意我们将geometry、config、title声明为self,这里self是新窗口,self.parent是window1

#declare class type directly...

class Window2(Toplevel):
    def __init__(self, parent):
    super().__init__()

    #Windows2 recive a parent....
    self.parent = parent
    self.geometry = ('1350x750+0+0')
    self.config(bg='powder blue')
    self.title('User Information and Payment')

and above all最重要的是

 #here the reference is wrong
    #name = Window1.txtofName.get()
    #the right reference is self.parent....
    name = self.parent.txtofName.get()
    self.FirstName = StringVar()
    #here, if you need to use the textvariable you must first assign it
    self.FirstName.set(name)

here the full story, try it.这里有完整的故事,试试吧。

from tkinter import *
from PIL import Image, ImageTk
import time
from tkinter import ttk

class Window1(object):
    def __init__(self, master):
        self.master = master
        self.master.geometry = ('1600x750+0+0')
        self.master.config(bg='powder blue')
        self.master.title('ALVO HOTEL')
        
        # ==========Framing============
        self.ftop = Frame(master, width=1600, height=100, bg='powder blue', relief=RIDGE, pady=20)
        self.ftop.grid(columnspan=3, column=0, row=0)
        self.f1 = Frame(master,width=800,height=700,relief=SUNKEN, bg='powder blue', pady=50, bd=3)
        self.f1.grid(column=1, row=2, sticky="nsew")
        self.f4 = Frame(master, width=100, height=700, relief=SUNKEN, bg='powder blue', pady=50, padx=20, bd=3)
        self.f4.grid(column=2, row=2, sticky="nsew")


        self.labelofName = Label(self.f1, font=('arial', 16, 'bold'), text='Name: ', bg='powder blue', bd=10, anchor=W)
        self.labelofName.grid(row=0, column=0, pady=(20, 10))
        self.txtofName = Entry(self.f1, font=('arial', 16, 'bold'), bd=10, insertwidth=4, bg='white', justify='left')
        self.txtofName.grid(row=0, column=1, pady=(20, 10))

        self.btnNext = Button(self.f1, padx=10, pady=8, bd=10, fg='white', font=('arial', 10, 'bold'), width=10, text='Next Page', bg='green', command=self.new_window_pop)
        self.btnNext.grid(row=6, column=1, sticky=E)
        
    def new_window_pop(self):
        #avoid declaring the class type here
        #Window2(Toplevel(self.master))
        #and pass self...self = master
        Window2(self)

#declare class type directly...
class Window2(Toplevel):
    def __init__(self, parent):
        super().__init__()

        #Windows2 recive a parent....
        self.parent = parent
        self.geometry = ('1350x750+0+0')
        self.config(bg='powder blue')
        self.title('User Information and Payment')

        #notice this Frame(self,....
        self.ftitle = Frame(self, bd=10, width=1350, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle.grid(columnspan=3, column=0, row=0)
        self.ftitle2 = Frame(self, bd=10, width=1350, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.ftitle2.grid(columnspan=3, column=0, row=3, pady=(0,20))
        self.fbutton = Frame(self, width=1350, height=50, bg='powder blue', relief=RIDGE, padx=10, pady=20)
        self.fbutton.grid(columnspan=3, column=0, row=2)
        self.finfomain = Frame(self, bd=10, width=1350, height=400, bg='powder blue', relief=RIDGE)
        self.finfomain.grid(columnspan=3, column=0, row=1)

        self.finfo1 = Frame(self.finfomain, bd=5, width=900, height=300, bg='powder blue', relief=RIDGE, padx=10)
        self.finfo1.grid(column=0, row=0)
        self.finfo1a = Frame(self.finfomain, bd=5, width=900, height=100, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo1a.grid(column=0, row=1)
        self.finfo2 = Frame(self.finfomain, bd=5, width=450, height=400, bg='powder blue', relief=RIDGE, padx=20)
        self.finfo2.grid(column=1, row=0, rowspan=2)

        #here the reference is wrong
        #name = Window1.txtofName.get()
        #the right reference is self.parent....
        name = self.parent.txtofName.get()
        self.FirstName = StringVar()
        #here, if you need to use the textvariable you must first assign it
        self.FirstName.set(name)

        self.lblfirstname = Label(self.finfo1, font=('arial', 16, 'bold'), bg='powderblue', text='First Name:', padx=2)
        self.lblfirstname.grid(row=0, column=0, sticky=W)
        self.txtfirstfname = Entry(self.finfo1, font=('arial', 16, 'bold'), textvariable=self.FirstName, bd=3, insertwidth=5, bg='white', justify='left')
        self.txtfirstfname.grid(row=0, column=1)

        
        
def main():
    root = Tk()
    app = Window1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM