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:
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:
- Create the outer layout (the one that will be set on the widget).
- Create the inner layout and add widgets to it.
- Add the inner layout to the outer layout using
addLayout(). - Call
self.setLayout()with the outer layout — just once.
Here's the corrected version:
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.
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:
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.
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.