PYQT - nesting widgets and layouts in multiple levels

10,917

Solution 1

You have to set the layout to the widget. E.g

self.main_CL = QtWidgets.QVBoxLayout()
self.main_CF.setLayout(self.main_CL)

Then add the subwidgets into the layout explicitly. E.g.

self.main_CL.addWidget(self.asset_CGF)

Follow the same pattern for sub components.

self.asset_CGF.setLayout(self.asset_CGL)
self.asset_CGL.addWidget(...)

Actually your first example is only missing two calls

self.main_CL.addWidget(self.asset_CGF)
self.main_CL.addWidget(department_CGF)

Solution 2

Including Aleš Erjavecs answer, this is the working codeexample:

class AssetCreationWindow(QtWidgets.QMainWindow):

def __init__(self, controller):
    super(AssetCreationWindow, self).__init__()
    self.controller = controller
    self.create_content()
    self.show()

def create_content(self):

# creating main container-frame, parent it to QWindow
    self.main_CF = QtWidgets.QFrame(self)
    self.main_CF.setStyleSheet('background-color: rgba(150, 0, 0, 1);')
    self.setCentralWidget(self.main_CF)
# creating layout and parent it to main container
# is it correct, that main_CL now manages children of main_CF ?
    self.main_CL = QtWidgets.QVBoxLayout(self.main_CF)


# creating the first subcontainer + layout, parenting it
    asset_CGF = QtWidgets.QFrame(self.main_CF)
    self.main_CL.addWidget(asset_CGF)
    asset_CGF.setStyleSheet('background-color: rgba(0, 150, 0, 1);')
    asset_CGL = QtWidgets.QHBoxLayout(asset_CGF)

# creating label and lineEdit, both are supposed to be on top of asset_CGF    
    asset_label = QtWidgets.QLabel("Assetname: ", asset_CGF)
    asset_CGL.addWidget(asset_label)
    asset_name = QtWidgets.QLineEdit("MyNewAsset", asset_CGF)
    asset_CGL.addWidget(asset_name)

# doing the same with a second container
    department_CGF = QtWidgets.QFrame(self.main_CF)
    self.main_CL.addWidget(department_CGF)
    department_CGF.setStyleSheet('background-color: rgba(0, 0, 150, 1);')
    department_CGL = QtWidgets.QHBoxLayout(department_CGF)

    department_label = QtWidgets.QLabel("Department: ", department_CGF)
    department_CGL.addWidget(department_label)

    department_names = QtWidgets.QComboBox(department_CGF)
    department_CGL.addWidget(department_names)

It results in this: window with nested QWidgets

Share:
10,917

Related videos on Youtube

Florian Graf
Author by

Florian Graf

Updated on September 16, 2022

Comments

  • Florian Graf
    Florian Graf over 1 year

    I am new to pyqt and trying to create a set of nested containers which hold my controls. I could not find any examples that nest widgets(and keep them layouted). I was able to nest layouts only, but thats not what i want to achieve. One reason i want to do this, is to have controle over the backgroundcolor of my containers. Since layouts do not have a color, i think i need QWidgets or QFrames. This is how far i came:

    class AssetCreationWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super(AssetCreationWindow, self).__init__()
            self.create_content()
            self.show()
    
        def create_content(self):
    
        # creating main container-frame, parent it to QWindow
            self.main_CF = QtWidgets.QFrame(self)
            self.main_CF.setStyleSheet('background-color: rgba(255, 0, 0, 1);')
            self.setCentralWidget(self.main_CF)
        # creating layout and parent it to main container
        # is it correct, that main_CL now manages children of main_CF ?
            self.main_CL = QtWidgets.QVBoxLayout(self.main_CF)
    
        # creating the first subcontainer + layout, parenting it
            asset_CGF = QtWidgets.QFrame(self.main_CF)
            asset_CGF.setStyleSheet('background-color: rgba(0, 255, 0, 1);')
            asset_CGL = QtWidgets.QHBoxLayout(asset_CGF)
    
        # creating label and lineEdit, both are supposed to be on top of asset_CGF    
            asset_label = QtWidgets.QLabel("Assetname: ", asset_CGF)
            asset_CGL.addWidget(asset_label)
            asset_name = QtWidgets.QLineEdit("MyNewAsset", asset_CGF)
            asset_CGL.addWidget(asset_name)
    
        # doing the same with a second container
            department_CGF = QtWidgets.QFrame(self.main_CF)
            department_CGF.setStyleSheet('background-color: rgba(0, 0, 255, 1);')
            department_CGL = QtWidgets.QHBoxLayout(department_CGF)
    
            department_label = QtWidgets.QLabel("Department: ", department_CGF)
            department_CGL.addWidget(department_label)
    
            department_names = QtWidgets.QComboBox(department_CGF)
            department_CGL.addWidget(department_names)
    

    Unfortunatly this approach stacks all Widgets in the top right corner on top of each other. Another one was to remove the ParentWidget from all Layouts except main_CL and use addLayout().

    def create_content(self):
    
        self.main_CF = QtWidgets.QFrame(self)
        self.setCentralWidget(self.main_CF)
        self.main_CL = QtWidgets.QVBoxLayout(self.main_CF)
    
        asset_CGF = QtWidgets.QFrame(self.main_CF)
        asset_CGF.setStyleSheet('background-color: rgba(255, 0, 0, 1);')
        asset_CGL = QtWidgets.QHBoxLayout()
        self.main_CL.addLayout(asset_CGL)
    
        asset_label = QtWidgets.QLabel("Asset Name: ", asset_CGF)
        asset_CGL.addWidget(asset_label)
        asset_name = QtWidgets.QLineEdit("MyNewAsset", asset_CGF)
        asset_CGL.addWidget(asset_name)
    
        department_CGF = QtWidgets.QFrame(self.main_CF)
        department_CGF.setStyleSheet('background-color: rgba(0, 255, 0, 1);')
        department_CGL = QtWidgets.QHBoxLayout()
        self.main_CL.addLayout(department_CGL)
    
        department_label = QtWidgets.QLabel("Department: ", department_CGF)
        department_CGL.addWidget(department_label)
        department_names = QtWidgets.QComboBox(department_CGF)
        department_CGL.addWidget(department_names)
    

    This looks better in general but the subcontainer layouts seem to no know about the subcontainers. Even though the controlers are parented to the subcontainers, the controlers are not ontop of the subcontainers. The subcontainers are again stacked at the top right corner. I am at my wit's end.

    • eyllanesc
      eyllanesc over 6 years
      You could show an image of what you want.
  • eyllanesc
    eyllanesc over 6 years
    When you pass a parent to the layout: self.main_CL = QtWidgets.QVBoxLayout(self.main_CF), It is similar to assigning a layout to the parent: self.main_CF.setLayout(self.main_CL)
  • eyllanesc
    eyllanesc over 6 years
    In other words, only one of these instructions is necessary.