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

How to emit signal from Dialog to a slot in MainWindow in PyQt



  • I'm getting started on PyQt5, I've been trying to learn about signals and slots as it seems to be the proper way to communicating between classes in PyQT.

    Below you'll find my code, let me walk trough the code with you as you'll better understand my problem.

    I have a mainwindow with a pushbutton

    • When the button is clicked, a dialog window is executed.
    • The User inputs some data in textLineEdits, then clicks on a "Add" button
    • The Data is dumped to a Json File

    And here's where I come to a halt:

    • When my data gets written in my Json file, I want to emit a signal with 2 strings as argument.
    • Connect the signal with a function in MainWindow class in order to add Items to my Combobox (the ComboBox is in the MainWindow)

    Here's my demonstration code:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    import sys
    
    import ui.mainwindow as MnWindow
    import ui.AddUserDialog as AddUserDialog
    
    class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
    
    	def __init__(self, parent=None):
    		super(MainWindow, self).__init__(parent)
    		self.setupUi(self)
    
    	self.pushButtonAddUser.clicked.connect(self.showDialog)
    
    	def showDialog(self):
    		d = AddUserDialog(self)
    		d.exec_()
    
    	#Catch the emited signal from AddUserDialog and connect it to AddToCombo function
    	def AddToCombo(self,first,last):
    		self.UserComboBox.addItem(first + ' ' + last)
    
    class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
    
    	def __init__(self,parent=None):
    		super(AddUserDialog,self).__init__(parent)
    		self.setupUi(self)
    
    	self.pushButtonAddUser.clicked.connect(self.AddUser)
    
    	def AddUser(self):
    		new_user = {
    		'firstname' : self.lineEditPrenom.text(),
    		'lastname' : self.lineEditNom.text(),
    		'Adresse' : self.lineEditAdresse.text(),
    		'Town' : self.lineEditVille.text(),
    		'ZipCode' : self.lineEditCodePostal.text(),	
    		}
    
    		with open('MyJsonFile.json','r') as f:
    			data = json.load(f)
    
    		data['users'].append(new_user)
    
    		with open('MyJsonFile.json','w') as f:
    			json.dump(data,f,indent=3)
    
    		#Emit signal with new_user['firstname'] & new_user['lastname'] as arguments
    
    		self.close()
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        form = MainWindow()
        form.show()
        app.exec_()
    

  • Lifetime Qt Champion

    Hi,

    This is a case where you do not need to do that.

    Since you have a dialog, you can simply make a getter that will return the values you are interested in. After exec is done, just grab the values and set them where appropriate.

    Signals and slots are great but you do not need them for everything.



  • @SGaist Hi,

    Thanks for your comment.

    Can you show me how to set a getter in this case?

    Indeed, I don't need to do this with signal/slots, but I still want to know how to do it as I'm going to use it for later projects.

    Regards,


  • Lifetime Qt Champion

    A getter is juste a Python method in your class that returns something.

    As for signals and slots, you can add the two signals you want to your dialog class and then connect them before calling exec.



  • @SGaist Thanks for your comment. I think I get it for the first solution.

    As for the signal method, I'm just starting to learn about signals in Pyqt, Can you show me, if I'm not asking too much, a code demonstration of how to implement this ?

    Thanks,


  • Lifetime Qt Champion



  • Hi @SGaist,

    I've been following the link you passed me, here's what I did:

    created a signal

    class AddUserDialog(QDialog):
    
        # define a signal that emits two strings
        user_added = QtCore.pyqtSignal(str, str)
    
        ...
    
        def AddUser(self):
            ...
    
            # emit signal
            self.user_added.emit(new_user['firstname'], new_user['lastname'])
            self.close()
    

    Connected the signal:

    class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
    
        ....
    
        def showDialog(self):
            d = AddUserDialog(self)
    
            # connect signal to appropriate slot
            d.user_added.connect(self.AddToCombo)
    
            d.exec_()
    

    Still It doesn't work, I get the following error:

    AttributeError: 'AddUserDialog' object has no attribute 'user_added'
    
    

    Any Idea Why this doesn't work?

    Thanks again,


  • Lifetime Qt Champion

    Can you provide a minimal runnable example that shows your issue ?


Log in to reply