How does widget visibility work in PyQt6? When I hide a parent widget, all the child widgets also get hidden. Does a compound widget only become invisible when all its child widgets are invisible, or does hiding the parent hide everything automatically?
Great question — widget visibility in Qt can seem a little confusing at first, because it works differently depending on whether you're hiding a parent or hiding individual children. Let's walk through how it actually works.
Widget visibility basics
Every widget in PyQt6 has a .setVisible() method, along with the convenience methods .show() and .hide(). These control whether a widget is drawn on screen:
widget.show() # Make visible
widget.hide() # Make invisible
widget.setVisible(True) # Same as .show()
widget.setVisible(False) # Same as .hide()
You can also check a widget's current visibility state using .isVisible().
Parent-child visibility
Here's where it gets interesting. Qt widgets exist in a parent-child tree. When you place a QLabel inside a QVBoxLayout on a QWidget, that label is a child of the widget. This parent-child relationship affects visibility in two directions.
Hiding a parent hides all its children
When you hide a parent widget, all of its children are hidden too — automatically. You don't need to manually hide each child. Calling .hide() on the parent is enough to make the entire subtree disappear from the screen:
parent_widget.hide() # All children disappear
This makes sense when you think about it: if the container isn't being drawn, there's nowhere to draw the children.
Showing a parent respects each child's own visibility
When you show a parent widget again, each child will reappear only if that child's own visibility hasn't been explicitly set to False. In other words, Qt remembers whether you individually hid a child. If you hid a specific child before hiding the parent, that child will stay hidden when the parent comes back.
Children can't be visible if their parent is hidden
A child widget cannot be visible on screen if any of its ancestors are hidden. Even if you call .show() on a child, it won't actually appear until its parent (and all ancestors up the tree) are also visible.
PyQt/PySide Office Hours 1:1 with Martin Fitzpatrick — Save yourself time and frustration. Get one on one help with your projects. Bring issues, bugs and questions about usability to architecture and maintainability, and leave with solutions.
This is what the Qt documentation means by:
If an ancestor is not visible, the widget won't become visible until all its ancestors are shown.
A practical example
Let's put this together with a working example. We'll create a window with a button that toggles the visibility of a container widget. That container holds several child widgets — and you'll see that hiding the container hides everything inside it at once:
import sys
from PyQt6.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Show and Hide Widgets")
# Main layout
main_layout = QVBoxLayout()
# Toggle button
self.toggle_button = QPushButton("Toggle Panel")
self.toggle_button.clicked.connect(self.toggle_panel)
main_layout.addWidget(self.toggle_button)
# A container widget with children
self.panel = QWidget()
panel_layout = QVBoxLayout()
panel_layout.addWidget(QLabel("Child Label 1"))
panel_layout.addWidget(QLabel("Child Label 2"))
panel_layout.addWidget(QPushButton("Child Button"))
self.panel.setLayout(panel_layout)
main_layout.addWidget(self.panel)
# Central widget
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
def toggle_panel(self):
if self.panel.isVisible():
self.panel.hide()
else:
self.panel.show()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
Run this and click the "Toggle Panel" button. You'll see the entire panel — including all three child widgets — appear and disappear together. You only need to call .hide() on the parent QWidget, and all its children go with it.
Using .setVisible() with boolean values
The .setVisible() method is especially handy when you want to tie visibility to a condition, since it accepts a boolean directly:
self.panel.setVisible(not self.panel.isVisible())
This single line replaces the if/else block in the toggle method above.
Hiding individual children
Sometimes you want to hide just one widget inside a container while keeping the rest visible. That works exactly as you'd expect:
import sys
from PyQt6.QtWidgets import (
QApplication,
QCheckBox,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Hide Individual Children")
layout = QVBoxLayout()
self.label_a = QLabel("Label A")
self.label_b = QLabel("Label B")
self.label_c = QLabel("Label C")
layout.addWidget(self.label_a)
layout.addWidget(self.label_b)
layout.addWidget(self.label_c)
# Checkboxes to toggle each label
self.check_a = QCheckBox("Show Label A")
self.check_a.setChecked(True)
self.check_a.toggled.connect(self.label_a.setVisible)
self.check_b = QCheckBox("Show Label B")
self.check_b.setChecked(True)
self.check_b.toggled.connect(self.label_b.setVisible)
self.check_c = QCheckBox("Show Label C")
self.check_c.setChecked(True)
self.check_c.toggled.connect(self.label_c.setVisible)
layout.addWidget(self.check_a)
layout.addWidget(self.check_b)
layout.addWidget(self.check_c)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
Here we connect each checkbox's toggled signal directly to the corresponding label's .setVisible() method. Since toggled emits a boolean and .setVisible() accepts a boolean, they connect perfectly with no extra code needed.
Summary
Widget visibility in PyQt6 follows straightforward rules:
- Hiding a parent automatically hides all of its children. You don't need to hide them individually.
- Showing a parent reveals its children, but only those that haven't been individually hidden.
- A child can never be visible if any of its ancestors are hidden — calling
.show()on the child alone won't work until the ancestor is shown too. - Use
.show()and.hide()for simple toggling, or.setVisible(bool)when you want to set visibility based on a condition.
The original question asked whether a compound widget only becomes invisible when all its children are invisible. It's actually the other way around: hiding the parent makes the entire group invisible in one step, regardless of the children's individual states. The children's own visibility settings are remembered and restored when the parent becomes visible again.
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.