Search code examples
pythonpython-3.xpyqtpyqt4

In PyQT how to open a child window that has access to the parent's attributes?


I have an engine module that contains several helper methods and attributes:

engine.py

class World:
    def __init__(self):
        # stuff

    def foo(a, b):
        c = a + b # trivial example
        return c

Then I have a main.py which incorporates the UI files (created in QtDesigner and converted to .py using a script I have):

main.py

from PyQt4 import QtGui
import design1
import design2
import engine

class MainWindow(QtGui.QMainWindow, design1.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.world = engine.World()

        self.new_window_button.clicked.connect(self.open_new_window)

    def open_new_window(self):
        self.window_to_open = ChildWindow(self)
        self.window_to_open.show()

class ChildWindow(QtGui.QMainWindow, design2.Ui_MainWindow):
    def __init__(self, parent):
        super(ChildWindow, self).__init__(parent)
        self.setupUi(self)
        print(self.world.foo(1, 2)) # trivial example

def main():
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()

If I take out the print line, ChildWindow opens fine. But with it in I get the error:

AttributeError: 'ChildWindow' object has no attribute 'world'

I know I'm doing something silly but I can't figure it out.

edited main.py

from PyQt4 import QtGui
import design1
import design2
import engine

class MainWindow(QtGui.QMainWindow, design1.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.world = engine.World()

        self.new_window_button.clicked.connect(self.open_new_window)

    def open_new_window(self):
        self.window_to_open = ChildWindow(self)
        self.window_to_open.show()

class ChildWindow(QtGui.QMainWindow, design2.Ui_MainWindow):
    def __init__(self, parent):
        super(ChildWindow, self).__init__(parent)
        self.setupUi(self)
        print(self.parent().world.foo(1, 2)) # trivial example

def main():
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()

I now get the error:

TypeError: foo() takes 2 positional arguments but 3 were given


Solution

  • The ChildWindow class does not have the attribute to world, but you can access it through the parent() function, which returns the parent since you have used the following statement: self.window_to_open = ChildWindow (self)

    You must change

    self.world.foo(1, 2)
    

    to

    self.parent().world.foo(1, 2)
    

    Your method must be declared as static since it does not use self as a parameter.

    class World:
        def __init__(self):
            # stuff
    
        @staticmethod
        def foo(a, b):
            c = a + b # trivial example
            return c
    

    or

    def foo(self, a, b):
        c = a + b # trivial example
        return c