Search code examples
pythonpyqtpyqt5qlayout

add background color to a layout which is a sublayout (inside another layout)


Layout structure:

self.mainLayout = QGridLayout()
self.subLayout1 = QGridLayout()
self.subLayout2 = QVBoxLayout()
...
...
... 
self.mainLayout.addLayout(subLayout1,0,0)

I have tried:

self.mainLayout = QGridLayout()
self.panel = QWidget()
self.subLayout1 = QGridLayout(self.panel) 
self.mainLayout.addLayout(subLayout1,0,0)
self.panel.setStylesheet("background-color: red;")
Error: QLayout::addChildLayout: layout "" already has a parent

This is how I have set my mainLayout color

self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.black)
        self.setPalette(p)

which needs on back when showing subLayout1, subLayout2 etc

How do I do that ?

Edit : Added MCVE ( A Minimal, Complete, verifiable example )

from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout
from PyQt5.QtCore import Qt


class Window(QMainWindow):

    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.setWindowTitle('MCVE')

        '''Window Background'''
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.darkYellow)
        self.setPalette(p)

        '''Core Layouts'''
        self.mainLayout = QGridLayout()
        self.picLayout = QHBoxLayout()
        self.redditSubs = QVBoxLayout()
        self.downloadBar = QHBoxLayout()
        self.panel = QWidget()
        self.profileInfo = QGridLayout(self.panel)

        '''Nested Layout'''
        self.mainLayout.addLayout(self.profileInfo, 0, 0)
        self.mainLayout.addLayout(self.picLayout, 0, 1)
        self.mainLayout.addLayout(self.redditSubs, 1, 0)
        self.mainLayout.addLayout(self.downloadBar, 1, 1)

        '''Widgets'''
        self.display = QLabel('QHBoxLayout()')
        self.download = QLabel('QHBoxLayout()')
        self.subs = QLabel('QVBoxLayout()')
        self.fileInfo = QLabel('QGridLayout()')

        '''AddWidgets'''
        self.picLayout.addWidget(self.display)
        self.downloadBar.addWidget(self.download)
        self.redditSubs.addWidget(self.subs)
        self.profileInfo.addWidget(self.fileInfo, 0, 0)

        '''Stylesheet'''
        self.panel.setStyleSheet("background-color: red;")

        '''Initiating  mainLayout '''
        self.window = QWidget()
        self.window.setLayout(self.mainLayout)
        self.setCentralWidget(self.window)


if __name__ == '__main__':
    app = QApplication([])
    w = Window()
    w.showNormal()
    app.exec_()

As said above, the code error QLayout::addChildLayout: layout "" already has a parent, if Stylesheet section is commented out, QGridLayout() label shows up on top of that darkyellow background and I want that background section to be red.


Solution

  • A QXLayout is not a visual element but a class that controls the position and especially the size of the widget that is assigned. So wanting to set a color to that class that is not a visual element makes no sense.

    On the other hand, the error is caused because the 2 following codes are equivalent:

    x = QXLayout(w)
    
    x = QXLayout()
    w.setLayout(x)
    

    In your case you have indicated that the layout "profileInfo" belongs to "panel" with the following code: self.profileInfo = QGridLayout(self.panel), but then you indicate that the same layout belongs to "mainLayout" through the following code: self.mainLayout.addLayout(self.profileInfo, 0, 0). So to avoid the warning you must pass replace the last code with self.mainLayout.addWidget(self.panel, 0, 0).

    Update:

    If you want a widget to be inside another one then it must be a child of the second one, so the "fileInfo" must be a child of "panel", but since you want it to occupy the entire size of the parent then you must use a layout.

    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout
    from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout
    from PyQt5.QtCore import Qt
    
    
    class Window(QMainWindow):
        def __init__(self, parent=None):
            super(Window, self).__init__(parent)
            self.setWindowTitle("MCVE")
    
            """Window Background"""
            self.setAutoFillBackground(True)
            p = self.palette()
            p.setColor(self.backgroundRole(), Qt.darkYellow)
            self.setPalette(p)
    
            """Core Layouts"""
            self.mainLayout = QGridLayout()
            self.picLayout = QHBoxLayout()
            self.redditSubs = QVBoxLayout()
            self.downloadBar = QHBoxLayout()
            self.profileInfo = QGridLayout()
    
            """Nested Layout"""
            self.mainLayout.addLayout(self.profileInfo, 0, 0)
            self.mainLayout.addLayout(self.picLayout, 0, 1)
            self.mainLayout.addLayout(self.redditSubs, 1, 0)
            self.mainLayout.addLayout(self.downloadBar, 1, 1)
    
            """Widgets"""
            self.display = QLabel("QHBoxLayout()")
            self.download = QLabel("QHBoxLayout()")
            self.subs = QLabel("QVBoxLayout()")
    
            self.fileInfo = QLabel("QGridLayout()")
    
            self.panel = QWidget()
    
            """AddWidgets"""
            self.picLayout.addWidget(self.display)
            self.downloadBar.addWidget(self.download)
            self.redditSubs.addWidget(self.subs)
            self.profileInfo.addWidget(self.panel, 0, 0)
    
            lay = QVBoxLayout(self.panel)
            lay.addWidget(self.fileInfo)
    
            """Stylesheet"""
            self.panel.setStyleSheet("background-color: red;")
    
            """Initiating  mainLayout """
            self.window = QWidget()
            self.window.setLayout(self.mainLayout)
            self.setCentralWidget(self.window)
    
    
    if __name__ == "__main__":
        app = QApplication([])
        w = Window()
        w.showNormal()
        app.exec_()
    

    enter image description here