Search code examples
pythonpython-3.ximagepyqt5qmdiarea

PyQt user logo in center of MDI Area


I have been working on PyQt QMainWindow QMdiArea Class. I have been able to change the background colour as it is needed for my application. However, I am unable to add a logo in the centre of the window.

I have tried QBrush but that just insert logo in full QMdiArea. Furthermore, I have tried paintEvent overridden method but that seems to not work.

Please find enclosed my code and snapshot of the code output below:

# Import necessary libraries
import sys

from PyQt5 import QtWidgets, QtGui
from PyQt5.QtGui import QColor, QBrush, QPainter
from PyQt5.QtWidgets import QStyleFactory, QWidget, QMainWindow, QMdiArea


class MDI_Window(QMainWindow, QWidget):
    def __init__(self):
        super().__init__()
        self.centralWidget = QWidget(self)
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)

        self.window_initialize()
        self.show()

    def window_initialize(self):
        title = 'MDI'
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon("Some_Icon.png"))
        self.setMinimumSize(800, 600)

        self.mdi.setBackground(QBrush(QColor(169, 169, 169)))

        self.showMaximized()

    def paintEvent(self, event):
        self.mdi.paintEvent(event)
        self.painter = QPainter(self)
        # For testing logo
        self.painter.drawPixmap(500, 500, 500, 500, QtGui.QPixmap("KDS_Main-Window.png"))


if __name__ == "__main__":
    # Create App with the design
    LMS_App = QtWidgets.QApplication(sys.argv)
    LMS_App.setStyle(QStyleFactory.create('Fusion'))

    a = MDI_Window()
    # Exit application when system is terminated
    sys.exit(LMS_App.exec_())

Output of Program with Area Needed for Logo


Solution

  • You cannot implement the paintEvent like that, mostly because a paintEvent has to be called by Qt and for the specific widget that is being painted. The paint event must be implemented in the widget.

    The easiest solution is to subclass the QMdiArea:

    class MdiArea(QMdiArea):
        def paintEvent(self, event):
            # call the base implementation to draw the default colored background
            super().paintEvent(event)
            # create the painter *on the viewport*
            painter = QPainter(self.viewport())
            painter.drawPixmap(500, 500, 500, 500, QtGui.QPixmap("KDS_Main-Window.png"))
    

    Note that:

    1. you shoud remove the paintEvent for the main window, now;
    2. as you can see, the painter is called on the viewport: this is mandatory for all QAbstractScrollArea subclasses;
    3. QPainter instances used in a paintEvent should not be set as instance attributes (as you can see, I didn't use self.painter), as the painter must be destroyed at the end of the function, otherwise you'll face performance and drawing issues; you could theoretically avoid this issue by manually calling painter.end(), but, since a new QPainter instance is most likely going to be recreated very soon and very often, making it a persistent attribute each time has really no use.