简体   繁体   English

如何在不同的 class 中调用包含 function 的 function?

[英]How to call a function that contains a function in a different class?

I am using Tkinter in Python 3, and have two windows, each represented by a class.我在 Python 3 中使用 Tkinter,并且有两个 windows,每个都由 ZA2F2ED4F8EBC2ABCBBD4C 表示。 I need to click a button in WindowB (my second class) that runs a method from WindowA (my first class).我需要单击 WindowB(我的第二类)中的一个按钮,该按钮运行 WindowA(我的第一类)中的方法。 This should be fine, however the method I am calling calls another method from WindowA (my first class).这应该没问题,但是我正在调用的方法从 WindowA (我的第一个类)调用另一个方法。 This results in the error: AttributeError: 'WindowB' object has no attribute 'functionB'.这会导致错误:AttributeError: 'WindowB' object has no attribute 'functionB'。 How would I fix this so I can run functionA in WindowB (2nd class) with no errors?我将如何解决这个问题,以便我可以在 WindowB(第二类)中运行 functionA 而没有错误? Code:代码:

from tkinter import *
from functools import partial

class WindowA(Frame):
    def __init__(self, master= None): # initialise Menu
        Frame.__init__(self, master) # initialise Frame
        self.master = master
        self.createWindow() # adds buttons

    def createWindow(self):
        self.pack(fill = BOTH, expand = 1)
        # lambda prevents self.changeWindow from executing before button pressed
        button1 = Button(self, text = 'Change to Window B', command = lambda: self.changeWindow(WindowB))
        button1.pack(fill = X, padx = 10, pady = 10)

        button2 = Button(self, text = 'Run Function A', command = lambda: self.functionA())
        button2.pack(fill = X, padx = 10, pady = 10)


    def changeWindow(self, object):
        root.withdraw()
        currentFrame = object(root)

    def functionA(self):
        print("I am function A.")
        self.functionB()

    def functionB(self):
        print("I am function B, called from function A.")

class WindowB(Toplevel):
    def __init__(self, master = None):
        Toplevel.__init__(self, master)
        self.master = master
        self.Window()

    def Window(self):
        button3 = Button(self, text = 'Run Function A', command = lambda:WindowA.functionA(self))
        button3.grid(row = 1, column = 0, padx = 10)

root = Tk()
app = WindowA(root)
root.mainloop()

The most common solution is to pass the instance of WindowA when creating WindowB , so that the latter can access methods in the former.最常见的解决方案是在创建WindowA时传递WindowB的实例,以便后者可以访问前者中的方法。

First, make sure that WindowB can accept the name of the other window:首先,确保WindowB可以接受另一个 window 的名称:

class WindowB(Toplevel):
    def __init__(self, master = None, windowA=None):
        Toplevel.__init__(self, master)
        self.master = master
        self.windowA=windowA
        self.Window()

Next, pass self as the windowA parameter when creating the instance of WindowB .接下来,在创建WindowB的实例时将self作为windowA参数传递。 I renamed object to self since you're passing a class rather than an instance of the class:我将object重命名为self因为您传递的是 class 而不是 class 的实例:

class WindowA(Frame):
    ...
    def changeWindow(self, cls):
        root.withdraw()
        currentFrame = cls(root, windowA=self)

You can then use self.windowA to call any method in that object:然后,您可以使用self.windowA调用 object 中的任何方法:

class WindowB(Toplevel):
    ...
    def Window(self):
        ...
        button3 = Button(self, text = 'Run Function A', command = lambda:self.windowA.functionA())
        ...

As an alternative answer, you could use the classmethod decorator:作为替代答案,您可以使用classmethod装饰器:

    def functionA(self):
        print("I am function A.")
        WindowA.functionB()

    @classmethod
    def functionB(cls):
        print("I am function B, called from function A.")

Note I am calling WindowA.functionB()注意我正在调用WindowA.functionB()

You're almost there, you only need to change just one thing in tge Window() method of class WindowB .您快到了,您只需在 class WindowB 的WindowB Window()方法中更改一件事。 You need to change it to be like so:您需要将其更改为:

button3 = Button(self, text = 'Run Function A', command = lambda:WindowA().functionA())
# instead of 
# button3 = Button(self, text = 'Run Function A', command = lambda:WindowA.functionA(self))

you have to create instance from WindowA class to use WindowA function您必须从 WindowA class 创建实例才能使用 WindowA function

class WindowB(Toplevel):
    def __init__(self, master=None):
        Toplevel.__init__(self, master)
        self.master = master
        self.Window()
        self.WindowA = WindowA()  # added here

    def Window(self):
        button3 = Button(self, text='Run Function A', command=lambda: self.WindowA.functionA())
        button3.grid(row=1, column=0, padx=10)

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

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