简体   繁体   English

Python Tkinter OOP继承

[英]Python Tkinter OOP Inheritance

I am trying to inherit some values from one class to a another one. 我试图从一个类继承一些值到另一个。 I am using the function super to inherit. 我正在使用函数super继承。 Below is a simplfied version of my problem. 下面是我的问题的简化版本。 Thank you for help. 谢谢你的帮助。

from tkinter import *
import random
class First(object):
    def __init__(self,master):
        super(First, self).__init__(master)
    def random(self):
        self._y = random.randint(11,20)
        self._x = random.randint(1,10)
    def random2(self):
        s = First(root)
        s.random()


class Second(Frame,First):
    def __init__(self,master):
        super(Second, self).__init__(master)
        self.grid()
        self.menuFrame = Frame(self)
        self.create_menu_widgets()
        self.menuFrame.grid()
    def create_menu_widgets(self):
          btnMainMenu = Button(self.menuFrame,font=("consolas",18,"bold"),text="Main Menu")
          btnMainMenu.pack()
    def print(self):
        print(self._y,self._x)



root = Tk()
x = Second(root)
x.random()
x.random2()
x.print()
root.configure(background   = 'green')
root.mainloop()

I keep on getting the error: 我继续得到错误:

super(First, self).__init__(master)
TypeError: object.__init__() takes no parameters

Please help me, I think the problem is where I have s=First(root). 请帮助我,我认为问题出在我有s = First(root)的地方。 Thanks for help. 感谢帮助。

When you call super on a class that is the highest in your hierarchy it will go object . 当您在层次结构中最高的类上调用super时,它将成为object object is the super class of all objects in Python. object是Python中所有对象的超类。 So super(First, self).__init__(master) will try to initialize the object not any of your classes. 因此, super(First, self).__init__(master)将尝试初始化object而不是您的任何类。 You can see this inheritance using the Class.__mro__ . 您可以使用Class.__mro__看到此继承。 To figure out what I'm talking about. 弄清楚我在说什么。

And inheriting from object? 从对象继承? That happens by default even if you don't specify anything. 即使您未指定任何内容,默认情况下也会发生这种情况。 So I guess you wanted to inherit from Frame as object doesn't make any sense. 因此,我想您想从Frame继承,因为object没有任何意义。

So change your code to this and it should be fixed. 因此,将您的代码更改为此,它应该是固定的。

from tkinter import *
import random
class First(Frame): # changed here
    def random(self):
        self._y = random.randint(11,20)
        self._x = random.randint(1,10)
    def random2(self):
        s = First(root)
        s.random()


class Second(First): # changed here 
    def __init__(self,master):
        super(Second, self).__init__(master)
        self.grid()
        self.menuFrame = Frame(self)
        self.create_menu_widgets()
        self.menuFrame.grid()
    def create_menu_widgets(self):
          btnMainMenu = Button(self.menuFrame,font=("consolas",18,"bold"),text="Main Menu")
          btnMainMenu.pack()
    def print(self):
        print(self._y,self._x)

root = Tk()
x = Second(root)
x.random()
x.random2()
x.print()
root.configure(background   = 'green') # you cannot see this as your button fills everything
root.mainloop()

I see several issues in your example. 我在您的示例中看到了几个问题。

1: 1:

you are assigning Second() to x but then calling x.random() and x.random2() . 您要为x分配Second() ,然后调用x.random()x.random2() This will not work as your random methods only exist in the First() class. 这将不起作用,因为您的随机方法仅存在于First()类中。

2: 2:

Don't name a function, method, variable or attribute the same thing as a built in method. 不要将函数,方法,变量或属性命名为与内置方法相同的名称。 This will cause problems. 这会引起问题。

Change your def print(self) to something like def my_print(self) or anything that is not exactly print . 将您的def print(self)更改为def my_print(self)东西或不完全是print任何东西。 While we are talking about this print statement you only define self._x and self._y in your First() class but try to print them in your Second() class. 在讨论此打印语句时,您仅在First()类中定义self._xself._y ,但尝试在Second()类中进行打印。 This will never work. 这将永远行不通。 self is always a reference to the class object and never a reference to a class controller that was passed to the class. self始终是对类对象的引用,而永远不是对传递给该类的类控制器的引用。

Now I get what you are trying to do here and I will rebuild your code to show how to share information between classes. 现在,我在这里得到了您想要做的事情,并且我将重建您的代码以显示如何在类之间共享信息。

You should not use a geometry manager fro inside the Frame class. 您不应在Frame类内部使用几何管理器。 Instead use it on the class variable name. 而是在类变量名称上使用它。 This will allow you chose between any geometry manager for the class instead of sticking to just one kind. 这样一来,您就可以在该类的任何几何管理器之间进行选择,而不必只遵循一种。

As Vineeth pointed out you do not use supper for an object class. 正如Vineeth指出的那样,您不要对对象类使用晚餐。

The below code will run the Second() class and then when you want to reference the random methods on the First() class you can do so with the new methods I added to Second() . 下面的代码将运行Second()类,然后当您要在First()类上引用随机方法时,可以使用我添加到Second()的新方法来实现。 Let me know if you have any questions. 如果您有任何疑问,请告诉我。

One last change is to import tkinter as tk this will help prevent accidentally overwriting an imported method from tkinter. 最后一个更改是将tkinter导入为tk这将有助于防止意外覆盖从tkinter导入的方法。

Here is a working example of your code: 这是您的代码的工作示例:

import tkinter as tk
import random


class First(object):
    def random(self):
        return "From First.Random!", random.randint(11,20), random.randint(1,10)

    def random2(self):
        return "From First.Random2!", self.random()


class Second(tk.Frame):
    def __init__(self, master):
        super(Second, self).__init__(master)
        self.menuFrame = tk.Frame(self)
        self.menuFrame.grid()
        tk.Button(self.menuFrame, font=("consolas", 18, "bold"), text="Main Menu").pack()

    def random(self):
        print(First().random())
    def random2(self):
        print(First().random2())


root = tk.Tk()
root.configure(background='green')

x = Second(root)
x.pack()
x.random()
x.random2()

root.mainloop()

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

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