0

I'm designing this thing on Qt Designer using PyQt. So I have a QMainWindow from where the user can open a QDialog to Input some data I'm saving in a Json file (AddUser function below)

What I want is when the AddUser push button is clicked, from the AddUser function, How can I Add a new Item in a Combobox that is defined in the MainWindow Class ?

Here is the code of the two classes

import ui.mainwindow as MnWindow
import ui.AddUserDialog as AddUserDialog

#First GUI
class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):

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

#Second GUI
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):
        DateDeNaissance = self.dateEditDateDeNaissance.date().toString(Qt.ISODate)
        DateDeSortie = self.dateEditDateDeSortie.date().toString(Qt.ISODate)
        new_user = {
        'firstname' : self.lineEditPrenom.text(),
        'lastname' : self.lineEditNom.text(),
        'DateDeNaissance' : DateDeNaissance[-2:] + DateDeNaissance[5:7] + DateDeNaissance[:4],
        'LieuDeNaissance' : self.lineEditLieuNaissance.text(),
        'Adresse' : self.lineEditAdresse.text(),
        'Ville' : self.lineEditVille.text(),
        'CodePostal' : self.lineEditCodePostal.text(),
        'DateDeSortie' : DateDeSortie[-2:] + DateDeSortie[5:7] + DateDeSortie[:4],      
        'Heure' : str(self.timeEditSortie.time().hour()),
        }

        with open('TestJson.json','r') as f:
            data = json.load(f)

        data['users'].append(new_user)

        with open('TestJson.json','w') as f:
            json.dump(data,f,indent=3)

        MainWindow.UserComboBox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])

The last line the incorrect of course, How can I do that properly ?

PS: I've read that I need to inherit from MainWindow Class, but I've been trying that with no success.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Hamouza
  • 356
  • 3
  • 12
  • Interactive dialogs are normally used to get *back* some result as soon as the dialog is closed (by *accepting* or *rejecting* it), and in normal situations they shouldn't be able to directly interact with the object that created them. So, the most important question is: do you want to be able to change the items in the main window while the dialog is still opened, or do you want to get back the results from the dialog and then react accordingly? – musicamante Nov 02 '20 at 18:43
  • @musicamante No, the changes in the mainWindow are made once the dialog is closed, How do I get to perform actions on the mainwindow widgets using the dialog results ? I'm new to Qt so I don't know if there's a easy obvious way to do this. Thanks, – Hamouza Nov 02 '20 at 23:12

2 Answers2

0

You can pass the combo box as an argument when you create an instance of AddUserDialog:

class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):

def __init__(self,parent=None, combobox= None):
    super(AddUserDialog,self).__init__(parent)
    self.setupUi(self)

    self.combobox = combobox

And in AddUser method, use self.combobox:

 # MainWindow.UserComboBox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])
 self.combobox.addItem(new_user['firstname'] + ' ' + new_user['lastname'])

Alternatively, you already know the parent of the dialog when you make an instance. I think the super(AddUserDialog,self).__init__(parent) line will set self.parent for the dialog. Then in AddUser method, use this statement:

self.parent.UserComboBox..addItem(new_user['firstname'] + ' ' + new_user['lastname'])
bfris
  • 5,272
  • 1
  • 20
  • 37
0

There are two possible ways to do so.

The simplest way is to access to the properties (or properties of widgets) from the reference to the instance.

class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.someButton.clicked.connect(self.addUser)

    def addUser(self):
        dialog = AddUserDialog(self)
        if dialog.exec_():
            firstname = dialog.lineEditPrenom.text()
            lastname = dialog.lineEditNom.text()
            self.UserComboBox.addItem('{} {}'.format(firstname, lastname))

Alternatively, you can overwrite the exec_() method of the dialog and return the values if the dialog is accepted:

class MainWindow(QMainWindow,MnWindow.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.addUserButton.clicked.connect(self.addUser)

    def addUser(self):
        res = AddUserDialog(self).exec_()
        if res:
            self.UserComboBox.addItem(res)


class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
    def exec_(self):
        if super().exec_():
            firstname = self.lineEditPrenom.text()
            lastname = self.lineEditNom.text()
            return '{} {}'.format(firstname, lastname)

Both solutions work with the assumption that the user is accepting the dialog, which normally happens by pressing an "Ok" button. If you want to use a custom button, you should also call self.accept() at the end of the AddUser() function.

Consider that Qt provides the QDialogButtonBox for this purpose, and you don't need to add your own buttons. I believe you're probably using a QPushButton because the default buttons of QDialogButtonBox have fixed labels and none of them has the "Add" text, but those buttons can be renamed as you wish. Assuming you have a QDialogButtonBox on your dialog named buttonBox (the default for dialogs with buttons) with an "Ok" button, you can implement the json writing directly in the accept() function:


class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
    def __init__(self,parent=None):
        super(AddUserDialog,self).__init__(parent)
        self.setupUi(self)

        self.buttonBox.button(self.buttonBox.Ok).setText('Add user')

    def accept(self):
        DateDeNaissance = self.dateEditDateDeNaissance.date().toString(Qt.ISODate)
        DateDeSortie = self.dateEditDateDeSortie.date().toString(Qt.ISODate)
        new_user = {
        'firstname' : self.lineEditPrenom.text(),
        'lastname' : self.lineEditNom.text(),
        'DateDeNaissance' : DateDeNaissance[-2:] + DateDeNaissance[5:7] + DateDeNaissance[:4],
        'LieuDeNaissance' : self.lineEditLieuNaissance.text(),
        'Adresse' : self.lineEditAdresse.text(),
        'Ville' : self.lineEditVille.text(),
        'CodePostal' : self.lineEditCodePostal.text(),
        'DateDeSortie' : DateDeSortie[-2:] + DateDeSortie[5:7] + DateDeSortie[:4],      
        'Heure' : str(self.timeEditSortie.time().hour()),
        }

        with open('TestJson.json','r') as f:
            data = json.load(f)

        data['users'].append(new_user)

        with open('TestJson.json','w') as f:
            json.dump(data,f,indent=3)

        super().accept()

Note that Designer automatically connects the accepted and rejected signals of the button box to the relative accept and reject slots of the dialog. If you don't want to rebuild the whole GUI and still add a button box, just create a new dialog with buttons and ctrl-drag the buttonbox to your existing interface, but you have to recreate the connections manually; you can do that using the signal/slot edit mode of Designer (Edit menu -> Edit Signals/Slots, or F4) or within your code:


class AddUserDialog(QDialog,AddUserDialog.Ui_Dialog):
    def __init__(self,parent=None):
        super(AddUserDialog,self).__init__(parent)
        self.setupUi(self)

        self.buttonBox.button(self.buttonBox.Ok).setText('Add user')

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    # ...
musicamante
  • 41,230
  • 6
  • 33
  • 58