QWidget::setLayout: Attempting to set QLayout on a widget which already has a layout

Understanding why calling setLayout() twice causes an error, and how to structure your layouts correctly
Heads up! You've already completed this tutorial.

I'm a beginner and I don't understand the error message: QWidget::setLayout: Attempting to set QLayout "" on Window "", which already has a layout. What does this mean and how do I fix it?

This is one of the most common layout errors you'll run into when starting out with PyQt6. Once you understand what's going on, it's straightforward to fix. Let's look at what causes it and how to structure your layouts properly.

What the error means

In Qt, every widget can have one layout assigned to it. When you call self.setLayout(some_layout), you're telling the widget: "Use this layout to arrange your child widgets." If you then call self.setLayout(another_layout) on the same widget, Qt complains because there's already a layout in place.

Here's a simplified version of the code that triggers the error:

python
lay_ver = QVBoxLayout()
self.setLayout(lay_ver)      # First layout set — this works fine

lay_hor = QHBoxLayout()
self.setLayout(lay_hor)      # Second layout set — ERROR!

That second call to self.setLayout() is the problem. The widget already has lay_ver as its layout, and you can't replace it by calling setLayout() again.

How to fix it: nest layouts instead

If you want to combine a vertical layout and a horizontal layout, you don't set both on the widget. Instead, you nest one layout inside the other and only call setLayout() once, at the end. For a full introduction to how layouts work in PyQt6, see the PyQt6 layouts tutorial.

The pattern looks like this:

  1. Create the outer layout (the one that will be set on the widget).
  2. Create the inner layout and add widgets to it.
  3. Add the inner layout to the outer layout using addLayout().
  4. Call self.setLayout() with the outer layout — just once.

Here's the corrected version:

python
import sys

from PyQt6.QtWidgets import (
    QApplication,
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QComboBox,
    QCheckBox,
)


class Window(QWidget):
    def __init__(self):
        super().__init__()

        # Create the outer vertical layout.
        lay_ver = QVBoxLayout()

        # Add a combo box to the vertical layout.
        self.combo_box = QComboBox()
        self.combo_box.addItems(["One", "Two", "Three"])
        self.combo_box.activated.connect(self.on_combo_box)
        lay_ver.addWidget(self.combo_box)

        # Create an inner horizontal layout.
        lay_hor = QHBoxLayout()
        self.check_box = QCheckBox("A")
        self.check_box.stateChanged.connect(self.on_check_box)
        lay_hor.addWidget(self.check_box)

        # Nest the horizontal layout inside the vertical layout.
        lay_ver.addLayout(lay_hor)

        # Set the layout on the widget — only once!
        self.setLayout(lay_ver)

    def on_check_box(self, state):
        print(state)

    def on_combo_box(self, index):
        print(index, self.combo_box.currentText())


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

Notice that self.setLayout(lay_ver) is called once, at the very end of __init__. The horizontal layout is added into the vertical layout with lay_ver.addLayout(lay_hor), so everything is arranged through a single layout hierarchy.

Visualizing the layout hierarchy

It can help to think of layouts as a tree. The outer layout is the root, and any nested layouts are branches. Widgets sit at the leaves.

python
QVBoxLayout (lay_ver)          ← set on the widget
├── QComboBox
└── QHBoxLayout (lay_hor)      ← added with addLayout()
    └── QCheckBox

You can nest as many layouts as you need. For example, you might have a vertical layout containing two horizontal layouts, each holding several buttons. The only rule is that you set one layout on the widget itself — the outermost one — and everything else gets nested inside it using addLayout().

What about QMainWindow?

You might also see this error when working with QMainWindow. That situation is slightly different but equally common.

QMainWindow is a special widget that comes with its own built-in layout. This internal layout handles the menu bar, toolbars, status bar, and dock widgets. Because of this, you cannot call setLayout() on a QMainWindow at all — the layout already exists and is managed by Qt.

Instead, QMainWindow expects you to set a central widget. The central widget is the main content area of the window. You create a plain QWidget, apply your layout to that widget, and then pass it to the main window using setCentralWidget(). If you're new to building applications with QMainWindow, the creating your first window tutorial walks you through the basics.

Here's what that looks like:

python
import sys

from PyQt6.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QComboBox,
    QCheckBox,
)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Create a container widget to hold our layout.
        container = QWidget()

        # Build the layout on the container, not on self.
        lay_ver = QVBoxLayout()

        self.combo_box = QComboBox()
        self.combo_box.addItems(["One", "Two", "Three"])
        self.combo_box.activated.connect(self.on_combo_box)
        lay_ver.addWidget(self.combo_box)

        lay_hor = QHBoxLayout()
        self.check_box = QCheckBox("A")
        self.check_box.stateChanged.connect(self.on_check_box)
        lay_hor.addWidget(self.check_box)

        lay_ver.addLayout(lay_hor)

        # Set the layout on the container widget.
        container.setLayout(lay_ver)

        # Tell the main window to use this container as its central widget.
        self.setCentralWidget(container)

    def on_check_box(self, state):
        print(state)

    def on_combo_box(self, index):
        print(index, self.combo_box.currentText())


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

The container QWidget acts as a middleman: you apply your layout to it, and then hand it off to QMainWindow with setCentralWidget(). This gives you full control over the arrangement of widgets in the main area of the window without conflicting with QMainWindow's built-in layout.

Quick summary

Situation What to do
Using QWidget as your window Call self.setLayout() once. Nest additional layouts with addLayout().
Using QMainWindow as your window Create a QWidget container, set your layout on it, then call self.setCentralWidget(container).

The rule is simple: one widget, one layout. If you need to combine multiple layouts, nest them. And if you're working with QMainWindow, remember to go through a central widget. Once you've got layouts under control, you can explore adding toolbars and menus or connecting signals and slots to make your application interactive.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

PyQt/PySide 1:1 Coaching with Martin Fitzpatrick

Save yourself time and frustration. Get one on one help with your Python GUI projects. Working together with you I'll identify issues and suggest fixes, from bugs and usability to architecture and maintainability.

Book Now 60 mins ($195)

Martin Fitzpatrick

QWidget::setLayout: Attempting to set QLayout on a widget which already has a layout was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.