Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to transfer data between two widgets if they can't get each other's instance directly



  • Hi guys,

    Looking at the code below, the widgetA and widgetB can communicate with each other because their instances can be accessed from mainwindow Class.

    But in my case, I am going to create extensions(widgetA and widgetB) from mainwindow , and the two sub widgets are in different project folders. I can't control how mainwindow initiates the two instances.

    In addition, widgetA and widgetB are not child widgets of mainwindow. So I cannot use findChild() to get instances from mainwindow.

    In such case, is there a way to make widgetA and widgetB transfer data by using signal/slot or other mechanism, if they can't get each other's instance?

    Cheers.

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class widgetB(QtWidgets.QWidget):
    
        procDone = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super(widgetB, self).__init__(parent)
    
            self.lineEdit = QtWidgets.QLineEdit(self)
            self.button = QtWidgets.QPushButton("Send Message to A", self)
            self.layout = QtWidgets.QHBoxLayout(self)
            self.layout.addWidget(self.lineEdit)
            self.layout.addWidget(self.button)
    
            self.button.clicked.connect(self.on_button_clicked)
    
        @QtCore.pyqtSlot()
        def on_button_clicked(self):
            self.procDone.emit(self.lineEdit.text())
    
        @QtCore.pyqtSlot(str)
        def on_procStart(self, message):
            self.lineEdit.setText("From A: " + message)
    
            self.raise_()
    
    
    class widgetA(QtWidgets.QWidget):
        procStart = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super(widgetA, self).__init__(parent)
    
            self.lineEdit = QtWidgets.QLineEdit(self)
            self.lineEdit.setText("Hello!")
    
            self.button = QtWidgets.QPushButton("Send Message to B", self)
            self.button.clicked.connect(self.on_button_clicked)
    
            self.layout = QtWidgets.QHBoxLayout(self)
            self.layout.addWidget(self.lineEdit)
            self.layout.addWidget(self.button)
    
        @QtCore.pyqtSlot()
        def on_button_clicked(self):
            self.procStart.emit(self.lineEdit.text())
    
        @QtCore.pyqtSlot(str)
        def on_widgetB_procDone(self, message):
            self.lineEdit.setText("From B: " + message)
    
            self.raise_()
    
    
    class mainwindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(mainwindow, self).__init__(parent)
    
            self.button = QtWidgets.QPushButton("Click Me", self)
            self.button.clicked.connect(self.on_button_clicked)
    
            self.setCentralWidget(self.button)
    
            self.widgetA = widgetA()
            self.widgetB = widgetB()
    
            self.widgetA.procStart.connect(self.widgetB.on_procStart)
            self.widgetB.procDone.connect(self.widgetA.on_widgetB_procDone)
    
        @QtCore.pyqtSlot()
        def on_button_clicked(self):
            self.widgetA.show()
            self.widgetB.show()
    
            self.widgetA.raise_()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        main = mainwindow()
        main.show()
        sys.exit(app.exec_())
    
    


  • @Zac15 said in How to transfer data between two widgets if they can't get each other's instance directly:

    In such case, is there a way to make widgetA and widgetB transfer data by using signal/slot or other mechanism, if they can't get each other's instance?

    Yes. It is main window which knows about both of them

    , the widgetA and widgetB can communicate with each other because their instances can be accessed from mainwindow Class.

    So let main window do the connect() of some signal emitted by one widget to some slot defined in the other widget. Your own signals and slots. Pass whatever minimal parameter(s) might be required to do whatever job. There should be no reason why one widget needs to actually access the other widget.

    You seem to already know this when I see you have self.procStart.emit(self.lineEdit.text())? And you have

            self.widgetA.procStart.connect(self.widgetB.on_procStart)
            self.widgetB.procDone.connect(self.widgetA.on_widgetB_procDone)
    

    Oh, I see, you seem to know this! Then

    But in my case, I am going to create extensions(widgetA and widgetB) from mainwindow , and the two sub widgets are in different project folders. I can't control how mainwindow initiates the two instances.

    I don't get this. If mainwindow has the two instances it should be able to do the connect(). So what is your exact situation?



  • Hi @JonB ,

    thank you for your reply.

    In my case, I don't have any control of the main window, so I can't get widgetA and widgetB objects in the main window.

    My question is if there is a way to send signal from widgetA, then widgetB can connect the signal without knowing(getting) widgetA object? Connecting a signal by the name of it.

    Because main window, widgetA, widgetB are in the same thread, is it possible to send signal to message(main) loop and catching it by the name?

    Cheers


  • Lifetime Qt Champion

    @Zac15 said in How to transfer data between two widgets if they can't get each other's instance directly:

    Connecting a signal by the name of it.

    Not possible, because objects emit signals. So, you need the emitting object and you need receiving object to connect. Somewhere in your application you should be able to have both instances to connect.

    "I don't have any control of the main window" - but in the code you posted you clearly create both objects in main window.



  • Hi @jsulm,

    If connecting a signal by its name is impossible, then I have to find another way to resolve the problem.

    Sorry, the code is just an example, while in my real work, I can't create objects in the main window.

    Thanks.

    Cheers.


  • Moderators

    @Zac15 said in How to transfer data between two widgets if they can't get each other's instance directly:

    I can't control how mainwindow initiates the two instances.

    1. Can you work together with the person(s) who have control over mainwindow?
    2. The mainwindow obviously has a reason to instantiate your widgets. Does it provide any mechanism for your widgets to send/receive data?


  • Hi @JKSH,

    I don't have any control to the mainwindow.

    But I contacted the mainwindow developers, and they told me a way to get the objects of the child widgets from mainwindow.

    They didn't document that, but there is an internal function to fetch children objects, which resolved my problem.

    Thanks for your help.


Log in to reply