alex_555
alex_555

Reputation: 1102

Sending Data from Child to Parent Window in PyQt5

What I can't do

I'm not able to send data back from a child to a parent window.

What I have

I've got a complex GUI with several windows sendíng data to child windows. Each window represents a unique Python-script in the same directory. There was no need to explicitely specify parents and childs, as the communication was always unidirectional (parent to child). However, now I need to send back data from childs to parents and can't figure out how to do this as each window (i.e. each class) has its own file.

Example

Here's a minimal example showing the base of what I want to accomplish. What it does: win01 opens win02 and win02 triggers func in win01.

# testfile01.py

import sys
from PyQt5.QtWidgets import *
import testfile02 as t02

class win01(QWidget):

    def __init__(self, parent=None):
        super(win01, self).__init__(parent)

        self.win02 = t02.win02()
        self.button = QPushButton("open win02", self)
        self.button.move(100, 100)
        self.button.clicked.connect(self.show_t02)

    def initUI(self):
        self.center

    def show_t02(self):
        self.win02.show()

    def func(self):
        print("yes!")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = win01()
    ex.show()
    sys.exit(app.exec_())

##########################################################################

# testfile02.py

from PyQt5.QtWidgets import *
import testfile01 as t01

class win02(QWidget):

    def __init__(self, parent=None):
        super(win02, self).__init__(parent)

        self.win01 = t01.win01()
        self.button = QPushButton()
        self.button.clicked.connect(self.win01.func)

    def initUI(self):
        self.center()

What I tried

Importing testfile01 in the second window always leads to the error: RecursionError: maximum recursion depth exceeded.

Then, I tried the following approaches, but they didn't work either:

The Question

Is there a solution how to properly trigger func in win01 from win02?

Upvotes: 4

Views: 3252

Answers (2)

eyllanesc
eyllanesc

Reputation: 243897

Why are you getting RecursionError: maximum recursion depth exceeded?

You are getting it because you have a circular import that generates an infinite loop, in testfile01 you are importing the file testfile02, and in testfile02 you are importing testfile01, .... So that is a shows of a bad design.


Qt offers the mechanism of signals for objects to communicate information to other objects, and this has the advantage of non-dependence between classes that is a great long-term benefit (as for example that avoids circular import), so for that reason I think it is the most appropriate.

For this I will create the clicked signal in the class win02 that will be triggered by the clicked signal of the button, and make that clicked signal call the func:

testfile01.py

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
import testfile02 as t02


class win01(QWidget):
    def __init__(self, parent=None):
        super(win01, self).__init__(parent)

        self.win02 = t02.win02()
        self.win02.clicked.connect(self.func)
        self.button = QPushButton("open win02", self)
        self.button.move(100, 100)
        self.button.clicked.connect(self.show_t02)

    def show_t02(self):
        self.win02.show()

    def func(self):
        print("yes!")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = win01()
    ex.show()
    sys.exit(app.exec_())

testfile02.py

from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout


class win02(QWidget):
    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(win02, self).__init__(parent)
        self.button = QPushButton("call to func")
        self.button.clicked.connect(self.clicked)
        lay = QVBoxLayout(self)
        lay.addWidget(self.button)

I recommend you read:

Upvotes: 4

Omi
Omi

Reputation: 121

Both the Widgets are independent and have no link in between. Set win01 parent of win02.

In class win01
Replace :

self.win01 = t02.win02()
#and
self.win02.show()

with:

self.win01 = t02.win02(self)
#and
self.win01.show()

and in class win02
Replace:

self.win02 = t01.win01()
#and
self.button.clicked.connect(self.win01.func)

with:

self.win02 = self.parent()
#and
self.button.clicked.connect(self.win02.func)

Upvotes: 1

Related Questions