Pavel.D
Pavel.D

Reputation: 581

Removing icon and style of QMdiSubWindow

I notice that windows from QMdiarea needs to be style customized. I want to remove icon which appears on topleft of QMdiSubWindow widget and at the same time change this ugly blue color of window to something which look pretty good.

I have tried my setWindowsflag, but no effect.

The code:

class Mywindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Mywindow, self).__init__(parent)
        
        self.setMinimumSize(QtCore.QSize(800,600))
        self.setWindowTitle('Customized style')
        self.mdiarea = QtWidgets.QMdiArea()
        self.setCentralWidget(self.mdiarea)
        self.mdiarea.setWindowTitle('Test')
        
        self.window = QtWidgets.QWidget()        
        self.mdiarea.addSubWindow(self.window)

if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('Fusion')
    view = Mywindow()
    view.showMaximized()
    sys.exit(app.exec_())

Current Display:

enter image description here

Wants to obtain:

enter image description here

Any idea how to achieve that?

Upvotes: 4

Views: 2625

Answers (2)

eyllanesc
eyllanesc

Reputation: 244182

At least there are 2 solutions:

1. Use Qt StyleSheet

You must use the "background" property of QMdiSubWindow: title to change the color, and to remove the icon the trick is to pass it an icon with transparent color

from PyQt5 import QtCore, QtGui, QtWidgets

QSS = """
QMdiSubWindow:title{
    background: lightgray;
}
"""


def create_icon_by_color(color):
    pixmap = QtGui.QPixmap(512, 512)
    pixmap.fill(color)
    return QtGui.QIcon(pixmap)


class Mywindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Mywindow, self).__init__(parent)
        self.setWindowTitle("Customized style")
        self.mdiarea = QtWidgets.QMdiArea()
        self.setCentralWidget(self.mdiarea)
        self.mdiarea.setWindowTitle("Test")

        self.window = QtWidgets.QWidget()
        self.window.setMinimumSize(320, 240)
        sw = self.mdiarea.addSubWindow(self.window)
        sw.setWindowIcon(create_icon_by_color(QtGui.QColor("transparent")))


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("Fusion")
    app.setStyleSheet(QSS)
    view = Mywindow()
    view.show()
    sys.exit(app.exec_())

enter image description here

As you can see in my operating system, it has a white color in the middle that is not desired that serves to color the title of the subwindow, maybe in another operating system it does not generate that problem.

2. Use a QProxyStyle

In this case you can modify the style so it should be a more robust solution than the previous one and should not have other styles. For a simple operation I have created a custom QMdiSubWindow.

from PyQt5 import QtCore, QtGui, QtWidgets

def create_icon_by_color(color):
    pixmap = QtGui.QPixmap(512, 512)
    pixmap.fill(color)
    return QtGui.QIcon(pixmap)


class TitleProxyStyle(QtWidgets.QProxyStyle):
    def drawComplexControl(self, control, option, painter, widget=None):
        if control == QtWidgets.QStyle.CC_TitleBar:
            if hasattr(widget, "titleColor"):
                color = widget.titleColor
                if color.isValid():
                    option.palette.setBrush(
                        QtGui.QPalette.Highlight, QtGui.QColor(color)
                    )
            option.icon = create_icon_by_color(QtGui.QColor("transparent"))
        super(TitleProxyStyle, self).drawComplexControl(
            control, option, painter, widget
        )


class MdiSubWindow(QtWidgets.QMdiSubWindow):
    def __init__(self, parent=None, flags=QtCore.Qt.Widget):
        super(MdiSubWindow, self).__init__(parent, flags)
        style = TitleProxyStyle(self.style())
        self.setStyle(style)
        self._titleColor = QtGui.QColor()

    @property
    def titleColor(self):
        return self._titleColor

    @titleColor.setter
    def titleColor(self, color):
        self._titleColor = color
        self.update()


class Mywindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Mywindow, self).__init__(parent)
        self.setWindowTitle("Customized style")
        self.mdiarea = QtWidgets.QMdiArea()
        self.setCentralWidget(self.mdiarea)
        self.mdiarea.setWindowTitle("Test")

        self.window = QtWidgets.QWidget()
        self.window.setMinimumSize(160, 120)

        sw = MdiSubWindow()
        sw.setWindowTitle("Test")
        sw.titleColor = QtGui.QColor("lightgray")
        sw.setWidget(self.window)
        self.mdiarea.addSubWindow(sw)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("Fusion")
    view = Mywindow()
    view.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 4

S. Nick
S. Nick

Reputation: 13681

Try it:

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QAction, QMenuBar, QWidget,
                             QMdiArea, QMdiSubWindow, QProxyStyle, QStyle, QVBoxLayout)
from PyQt5.QtGui     import (QIcon, QPainter, QPalette, QPixmap)
from PyQt5.QtCore    import Qt, QSize


class MDIArea(QMdiArea):
    def __init__(self, *args, **kwargs):
        super(MDIArea, self).__init__(*args, **kwargs)  
        self.parent = args[0]
        self.background_pixmap = self.parent.pixmap 
        self.centered          = False

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self.viewport())
        if not self.centered:
            painter.drawPixmap(0, 0, self.width(), self.height(), self.background_pixmap)
        painter.end()


class Mywindow(QMainWindow):
    count = 1
    def __init__(self, parent=None):
        super(Mywindow, self).__init__(parent)
        self.setWindowTitle('Customized style')
        self.setWindowIcon(QIcon("im.png"))

#        self.mdiarea = QMdiArea()
        self.pixmap = QPixmap()
        self.pixmap.load("im.png")
        self.mdiarea = MDIArea(self)

        self.setCentralWidget(self.mdiarea)
#        self.mdiarea.setWindowTitle('Test')

        self.window = QWidget()   
        sub = QMdiSubWindow()
        sub.resize(QSize(200,200))
        sub.setAttribute(Qt.WA_DeleteOnClose)
        sub.setWidget(self.window) 
        sub.setWindowTitle("Test {}".format(self.count))            # +++
        sub.setWindowIcon(QIcon("im.png"))

        self.mdiarea.addSubWindow(sub)
        sub.show()          


style = """
QWidget {
    color: #ffdd00;
    background-color: #eee;
}
QMainWindow {
    color: #ffdd00;
    background-color: #ff3333;
}
"""

if __name__ == "__main__":
    app = QApplication([])
    app.setStyleSheet(style)          

#    app.setStyle('Fusion')                                        # ---

    view = Mywindow()
#    view.showMaximized()
    view.resize(500, 500)
    view.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 3

Related Questions