Search code examples
pythonmodel-view-controllerdialogpyqt4exit

Cannot close Dialog on Python PyQt4


My program has a MainWindow which contains my inventory system. I have added a Dialog window which pop-ups when I clicked "Add Item". I am able to successfully open the Dialog window but I can't seem to close it.

When the user tries to close the Dialog Window, it will display a messagebox asking if the user really wants to close the window. Currently, I'm using self.close(). It just closes the MessageBox I've made to prevent accidental exit and doesn't close the Dialog window unless you end it using the IDE or task manager.

Here's my code snippets:

Main.py

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)

        self.db = Database()
        self.model = Model(self)
        self.ui = MainWindow_ui()
        self.ui.setupUi(self)
        self.window = Ui_Dialog()

        self.ui.addItem.clicked.connect(lambda : self.start_Form())

    def start_Form(self):
        window = QtGui.QDialog()
        self.window.setupUi(window)
        self.window.show()

def main():
    app = QtGui.QApplication(sys.argv)
    window = Main()
    window.showMaximized()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

AddItem.py (contains the Dialog Window code)

def getNumber():
    conn = sqlite3.connect('inventory.db')
    c = conn.cursor()
    c.execute('SELECT seq FROM sqlite_sequence')
    itemNumber = c.fetchone()[0]
    return int(itemNumber) + 1

class Ui_Dialog(QtGui.QDialog):
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)

    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(413, 382)

        self.buttonBox = QtGui.QDialogButtonBox(Dialog)
        self.buttonBox.setStandardButtons(
            QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Reset)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    def retranslateUi(self, Dialog):    
        self.itemCode.setText(str(getNumber()))

    def accept(self):
        row = self.mapper.currentIndex()
        self.mapper.submit()
        self.main.model.insertRow(row)
        self.mapper.setCurrentIndex(row)

        self.close()

    def reject(self):
        ret = QtGui.QMessageBox.question(None, 'Close request', 'Are you sure you want to quit?',
                                         QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if ret == QtGui.QMessageBox.Yes:
            self.close()
        else:
            pass

Solution

  • Your accept() and reject() methods effectively create an infinite loop, because calling close() will, in turn, just call those methods again. When overriding virtual methods, you should call the base-class implementation using super:

    class Ui_Dialog(QtGui.QDialog):
        ...
    
        def accept(self):
            ...
            super(Ui_Dialog, self).accept()  
    
        def reject(self):
            ...
            if ret == QtGui.QMessageBox.Yes:
                super(Ui_Dialog, self).reject()