Search code examples
pythonqtpyqtpysidesignals-slots

Sending messages between two widgets using Signals and Slots


I need to have widgets communicating between each other.

My central Widget has 2 widget instances: widget A (instance of A()), widget B (instance of B()) When a widget A is subject to an event (e.g.: mouseRelease), I need widget A to call a function and to do some computing, processing data. And then I need this processed data to be passed to the widget B, which in turn upon receiving this data from widget A, will call a function with this data, process it, and do something more with it.

Both these widgets are custom widgets derived from QWidget. I am almost certain I need to use signals and slots but I don't understand how to implement function call parts.

I've read over and over again explanations of Qt here: http://qt-project.org/wiki/Signals_and_Slots_in_PySide however I can not figure it out how to connect two widgets which both process data emitted and sent.

I would really appreciate some help here. If you can not answer in Python yet competent with C++, please explain nonetheless using it instead of refraining at all.


Solution

  • Here is a example demonstrating signals/slots connections between two widgets in PyQt4:

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    
    from PyQt4 import QtCore, QtGui
    
    class widgetB(QtGui.QWidget):
        procDone = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super(widgetB, self).__init__(parent)
    
            self.lineEdit = QtGui.QLineEdit(self)
            self.button = QtGui.QPushButton("Send Message to A", self)
            self.layout = QtGui.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(QtGui.QWidget):
        procStart = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super(widgetA, self).__init__(parent)
    
            self.lineEdit = QtGui.QLineEdit(self)
            self.lineEdit.setText("Hello!")
    
            self.button = QtGui.QPushButton("Send Message to B", self)
            self.button.clicked.connect(self.on_button_clicked)
    
            self.layout = QtGui.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(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(mainwindow, self).__init__(parent)
    
            self.button = QtGui.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  = QtGui.QApplication(sys.argv)
        main = mainwindow()
        main.show()
        sys.exit(app.exec_())