Search code examples
pythonuser-interfacepyqt5method-resolution-order

MRO error in PyQt5 when using multiple inheritance


I'm new to PyQt5. I'm trying to create a single window with a menuBar (which inherits from the QMainWindow class) and some other widgets such as a button, some labels and text editors (which require the QWidget class). This is my code. When i try to add QMainWindow and QWidget as parent classes to may mainwindow class, i get an error saying: "TypeError: Cannot create a consistent method resolution order (MRO) for bases QWidget, QMainWindow". when i use only 1 parent class for mainwindow class it works fine, but in this case i have to use both QMainWindow and QWidget as parent classes.

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QAction, QMenu, QMainWindow, QTextEdit, QLineEdit, QGridLayout, QLabel

class mainwindow(QWidget, QMainWindow):
    def __init__(self):
        super().__init__()

        self.createUI()
    def createUI(self):
        mymenubar = self.menuBar()
        filemenu = mymenubar.addMenu("File")
        filemenu.addAction("help")
        filemenu.addAction("exit")



        contactlabel = QLabel("Contact:", self)
        contacttextedit = QLineEdit(self)
        countlabel = QLabel("Count:")
        counttextedit = QLineEdit()
        msglabel = QLabel("Your message here:")
        msgbox = QTextEdit()

        grid = QGridLayout()
        grid.setSpacing(10)




        grid.addWidget(contactlabel,1,0)
        grid.addWidget(contacttextedit,1,1)

        grid.addWidget(countlabel,2,0)
        grid.addWidget(counttextedit,2,1)

        grid.addWidget(msglabel,3,0)
        grid.addWidget(msgbox,3,1,5,1)

        self.setLayout(grid)
        self.setGeometry(300,300,300,300)
        self.setWindowTitle("Whatsapp Message Sender")
        self.show()



    # MODIFYING CLOSE EVENT SO IT ASKS BEFORE EXIT
    def closeEvent(self, event):
        reply = QMessageBox.question(self, "Message", "quit?", QMessageBox.Yes| QMessageBox.No, QMessageBox.Yes)

        if reply == QMessageBox.No:
            event.ignore()
        else:
            event.accept()



app = QApplication(sys.argv)
ex = mainwindow()
sys.exit(app.exec_())

What am i doing wrong? how can i use both QWidget and QMainwindow in my class?


Solution

  • You have 2 errors:

    • QMainWindow already inherits from QWidget so multiple inheritance is unnecessary causing the error.

    • You should not establish a layout to a QMainWindow since it already has a predefined structure, instead you must create a central container where the layout is.

    Considering the above, the solution is:

    import sys
    from PyQt5.QtWidgets import (
        QApplication,
        QWidget,
        QPushButton,
        QMessageBox,
        QAction,
        QMenu,
        QMainWindow,
        QTextEdit,
        QLineEdit,
        QGridLayout,
        QLabel,
    )
    
    
    class mainwindow(QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.createUI()
    
        def createUI(self):
            mymenubar = self.menuBar()
            filemenu = mymenubar.addMenu("File")
            filemenu.addAction("help")
            filemenu.addAction("exit")
    
            contactlabel = QLabel("Contact:", self)
            contacttextedit = QLineEdit(self)
            countlabel = QLabel("Count:")
            counttextedit = QLineEdit()
            msglabel = QLabel("Your message here:")
            msgbox = QTextEdit()
    
            grid = QGridLayout()
            grid.setSpacing(10)
    
            grid.addWidget(contactlabel, 1, 0)
            grid.addWidget(contacttextedit, 1, 1)
    
            grid.addWidget(countlabel, 2, 0)
            grid.addWidget(counttextedit, 2, 1)
    
            grid.addWidget(msglabel, 3, 0)
            grid.addWidget(msgbox, 3, 1, 5, 1)
    
            # self.setLayout(grid)
            central_widget = QWidget()
            central_widget.setLayout(grid)
            self.setCentralWidget(central_widget)
            self.setGeometry(300, 300, 300, 300)
            self.setWindowTitle("Whatsapp Message Sender")
            self.show()
    
        # MODIFYING CLOSE EVENT SO IT ASKS BEFORE EXIT
        def closeEvent(self, event):
            reply = QMessageBox.question(
                self, "Message", "quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes
            )
    
            if reply == QMessageBox.No:
                event.ignore()
            else:
                event.accept()
    
    
    if __name__ == "__main__":
    
        app = QApplication(sys.argv)
        ex = mainwindow()
        sys.exit(app.exec_())