Understanding .parent() vs. Parent Class in PyQt6 Custom Widgets

Why self.parent() doesn't mean what you think it means
Heads up! You've already completed this tutorial.

In a custom widget example, the _Bar class uses self.parent() to access a QDial object defined in the PowerBar class. But _Bar inherits from QWidget — so shouldn't self.parent() refer to QWidget? What's going on here?

This is one of those moments where two completely different concepts share similar names, and it can trip you up if you're not expecting it. In Python, we talk about parent classes (the class you inherit from). In Qt, .parent() refers to something else entirely — the parent widget in Qt's object hierarchy. Let's look at both, side by side, so the difference is clear.

Python Inheritance: The Parent Class

When you create a class that inherits from another class, the class you inherit from is sometimes called the "parent class" or "superclass." For example:

python
from PyQt6.QtWidgets import QWidget

class _Bar(QWidget):
    pass

Here, QWidget is the parent class of _Bar. You access the parent class's methods through super() — for example, super().__init__() calls QWidget.__init__(). This is standard Python and has nothing to do with Qt specifically. If you need a refresher on how inheritance works, see our guide to Python classes.

Qt's Parent-Child Relationship: .parent()

Qt has its own concept of parent-child relationships, and it operates at the instance level, not the class level. When you create a widget and pass another widget as its parent, Qt establishes an ownership relationship between those two objects.

python
from PyQt6.QtWidgets import QApplication, QWidget, QLabel

app = QApplication([])

window = QWidget()
label = QLabel("Hello!", parent=window)

print(label.parent())  # <PyQt6.QtWidgets.QWidget object at ...> — this is `window`

Here, label.parent() returns window — the specific QWidget instance that owns the label. It does not return QLabel's superclass (QFrame), and it has nothing to do with class inheritance.

The Qt parent is the container widget — the widget that this widget lives inside.

How This Works in a Custom Widget

Let's look at a simplified version of the PowerBar custom widget example to see both concepts in action:

python
from PyQt6.QtWidgets import QApplication, QWidget, QDial, QVBoxLayout
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPainter, QColor

class _Bar(QWidget):
    """A custom bar display widget."""

    def __init__(self, parent=None):
        super().__init__(parent)  # Python parent class: QWidget
        # At this point, self.parent() returns whatever `parent` was passed in.

    def paintEvent(self, event):
        painter = QPainter(self)
        # Access the dial value from the Qt parent widget
        parent = self.parent()  # Qt parent: the PowerBar instance
        value = parent.dial.value()
        painter.fillRect(0, 0, int(self.width() * value / 100), self.height(), QColor("green"))
        painter.end()


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

        layout = QVBoxLayout(self)

        # _Bar is created with `self` as its Qt parent
        self.bar = _Bar(self)
        self.bar.setFixedHeight(30)
        layout.addWidget(self.bar)

        self.dial = QDial()
        self.dial.setRange(0, 100)
        self.dial.valueChanged.connect(self.bar.update)
        layout.addWidget(self.dial)


app = QApplication([])
window = PowerBar()
window.show()
app.exec()

When PowerBar.__init__ runs, it creates _Bar(self). That self is the PowerBar instance, and it gets passed as the parent argument to _Bar.__init__. From that moment on:

The complete guide to packaging Python GUI applications with PyInstaller.
[[ discount.discount_pc ]]% OFF for the next [[ discount.duration ]] [[discount.description ]] with the code [[ discount.coupon_code ]]

Purchasing Power Parity

Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]

  • super().__init__(parent) calls QWidget.__init__() — that's Python's class inheritance at work.
  • self.parent() on the _Bar instance returns the PowerBar instance — that's Qt's object hierarchy at work.

Because self.parent() returns the PowerBar instance, _Bar can reach self.parent().dial and read the dial's current value. The two widgets are connected through Qt's parent-child ownership, not through class inheritance.

A Quick Comparison

Python Inheritance Qt Parent-Child
What is it? A class inherits behavior from another class A widget instance is owned by another widget instance
How you set it up class _Bar(QWidget) _Bar(parent=self)
How you access it super() self.parent()
Relationship between Classes Object instances
Example _Bar inherits from QWidget A _Bar instance is owned by a PowerBar instance

Why Qt Has Parent-Child Relationships

Qt uses the parent-child system for two practical reasons:

  1. Memory management. When a parent widget is deleted, all its child widgets are automatically deleted too. This prevents memory leaks — you don't have to manually clean up every label, button, and layout inside a window.

  2. Layout and visibility. Child widgets are drawn inside their parent. When you hide or move a parent widget, all its children go with it. This is how complex UIs stay organized — and it's closely related to how layouts arrange widgets within a window.

Complete Working Example

Here's a full example you can run that prints both the Python parent class and the Qt parent to make the distinction concrete:

python
import sys
from PyQt6.QtWidgets import (
    QApplication, QWidget, QDial, QVBoxLayout, QLabel
)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPainter, QColor


class _Bar(QWidget):
    """A simple bar that reflects the dial's value."""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFixedHeight(30)

        # Show the difference
        print(f"Python parent class (via super): QWidget")
        print(f"Qt parent instance (via self.parent()): {self.parent()}")
        print(f"Qt parent type: {type(self.parent())}")

    def paintEvent(self, event):
        painter = QPainter(self)

        # Use the Qt parent to access sibling data
        parent = self.parent()
        if parent and hasattr(parent, "dial"):
            value = parent.dial.value()
            bar_width = int(self.width() * value / 100)
            painter.fillRect(0, 0, bar_width, self.height(), QColor("#2ecc71"))

        painter.end()


class PowerBar(QWidget):
    """A compound widget with a bar display and a dial control."""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("PowerBar — .parent() Demo")

        layout = QVBoxLayout(self)

        self.bar = _Bar(self)  # `self` (PowerBar instance) becomes the Qt parent
        layout.addWidget(self.bar)

        self.dial = QDial()
        self.dial.setRange(0, 100)
        self.dial.setValue(25)
        self.dial.valueChanged.connect(self.bar.update)
        layout.addWidget(self.dial)

        label = QLabel("Drag the dial to change the bar")
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(label)


app = QApplication(sys.argv)
window = PowerBar()
window.show()
sys.exit(app.exec())

When you run this, the console output will show something like:

python
Python parent class (via super): QWidget
Qt parent instance (via self.parent()): <__main__.PowerBar object at 0x...>
Qt parent type: <class '__main__.PowerBar'>

The Qt parent is the PowerBar instance — the widget that owns _Bar — while the Python parent class remains QWidget. Two different relationships, two different meanings, sharing one unfortunately overloaded word.

To understand more about how Qt widgets communicate with each other, take a look at our tutorial on signals, slots and events in PyQt6.

PyQt/PySide Development Services — Stuck in development hell? I'll help you get your project focused, finished and released. Benefit from years of practical experience releasing software with Python.

Find out More

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

Understanding .parent() vs. Parent Class in PyQt6 Custom Widgets was written by Martin Fitzpatrick.

Martin Fitzpatrick is the creator of Python GUIs, and has been developing Python/Qt applications for the past 12+ years. He has written a number of popular Python books and provides Python software development & consulting for teams and startups.