If you've ever tried to set a title on a QMenu in PyQt6, you've probably noticed something frustrating: calling setTitle() on a menu doesn't actually display a title on the popup itself. The title property on QMenu is used for something else entirely — it's the text that appears when the menu is added to a QMenuBar (like "File", "Edit", etc.). When you show a QMenu as a standalone context menu, that title is invisible.
So how do you show a visible heading at the top of a context menu? There are a few approaches, each with their own trade-offs. In this tutorial, we'll walk through all of them and finish with the most flexible solution: embedding a QLabel widget directly in the menu using QWidgetAction.
Why setTitle() Doesn't Work
When you create a QMenu and call setTitle(), you're setting the label that would appear on a menu bar. For example:
menu = QMenu()
menu.setTitle("My Menu")
If you added this menu to a QMenuBar, you'd see "My Menu" as a clickable item on the bar. But when you show this menu as a popup context menu (using .show() or .exec()), that title is nowhere to be seen.
This catches a lot of people off guard, but once you know why it works this way, you can reach for the right solution.
Using addSection()
Qt provides a built-in method called addSection() that's designed to add labeled section headers to a menu. You might think this is exactly what you need — and depending on your platform and theme, it might be.
menu = QMenu()
menu.addSection("My Menu Title")
menu.addAction("Option 1")
menu.addAction("Option 2")
The catch is that addSection() renders differently depending on the platform style. On macOS and Windows native themes, it often looks identical to a plain separator line — the text simply doesn't show up.
The one reliable way to make addSection() visible is to use the Fusion style, which is Qt's built-in cross-platform theme:
app = QApplication(sys.argv)
app.setStyle("Fusion")
With Fusion active, addSection() displays the section text alongside a separator line, which looks quite nice. The downside is that Fusion doesn't match the native look and feel of any operating system, so your entire application will look slightly different from other apps on the user's desktop.
Packaging Python Applications with PyInstaller by Martin Fitzpatrick — This step-by-step guide walks you through packaging your own Python applications from simple examples to complete installers and signed executables.
Using a Disabled Action
A simpler workaround is to add a regular action and then disable it. A disabled action shows its text but appears grayed out and can't be clicked:
menu = QMenu()
title_action = menu.addAction("My Menu Title")
title_action.setDisabled(True)
menu.addSeparator()
menu.addAction("Option 1")
menu.addAction("Option 2")
This works on all platforms and themes. The text shows up, and users can't accidentally click on it. However, it looks like a disabled menu item, which could be confusing — users might wonder what they need to do to enable it.
Using a QLabel with QWidgetAction
The most flexible approach is to embed a QLabel widget directly into the menu using QWidgetAction. This lets you fully control the appearance of the title — you can center it, make it bold, change its background color, and more.
Here's how it works. First, create a QLabel with the text you want:
from PyQt6.QtWidgets import QLabel, QWidgetAction, QSizePolicy
from PyQt6.QtCore import Qt
label = QLabel("My Menu Title")
label.setAlignment(Qt.AlignCenter)
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
Then wrap the label in a QWidgetAction and add it to the menu. Note that the parent of the QWidgetAction should be the menu itself (not the label) — this ensures proper memory management and avoids crashes:
menu = QMenu()
widget_action = QWidgetAction(menu)
widget_action.setDefaultWidget(label)
menu.addAction(widget_action)
menu.addSeparator()
menu.addAction("Option 1")
menu.addAction("Option 2")
You can style the label however you like. For example, to make it bold with a colored background:
label.setStyleSheet("font-weight: bold; background-color: #e0e0e0; padding: 4px;")
This approach works reliably across all platforms and themes, and gives you complete control over how the title looks.
Complete Working Example
Here's a full example that demonstrates all three approaches side by side. Right-click anywhere in the window to see a context menu with a QLabel-based title. You can uncomment the alternative approaches to compare them.
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QMenu, QLabel,
QWidgetAction, QSizePolicy
)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QMenu Title Example")
self.resize(400, 300)
label = QLabel("Right-click anywhere in this window")
label.setAlignment(Qt.AlignCenter)
self.setCentralWidget(label)
def contextMenuEvent(self, event):
menu = QMenu(self)
# --- Approach 1: QLabel with QWidgetAction (recommended) ---
title_label = QLabel("My Menu Title")
title_label.setAlignment(Qt.AlignCenter)
title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
title_label.setStyleSheet(
"font-weight: bold; padding: 4px;"
)
title_action = QWidgetAction(menu)
title_action.setDefaultWidget(title_label)
menu.addAction(title_action)
# --- Approach 2: Disabled action (uncomment to try) ---
# title_action = menu.addAction("My Menu Title")
# title_action.setDisabled(True)
# --- Approach 3: addSection (uncomment to try, works best with Fusion) ---
# menu.addSection("My Menu Title")
menu.addSeparator()
menu.addAction("Select All")
menu.addAction("Copy")
menu.addAction("Paste")
menu.addSeparator()
menu.addAction("Settings...")
menu.exec(event.globalPos())
if __name__ == "__main__":
app = QApplication(sys.argv)
# Uncomment the next line to try the Fusion style with addSection()
# app.setStyle("Fusion")
window = MainWindow()
window.show()
sys.exit(app.exec())
When you run this and right-click in the window, you'll see a context menu with a bold, centered title at the top.
The QWidgetAction approach is the most versatile because you have full control over the widget. You could swap the QLabel for any widget — even a small layout with an icon and text, if you wanted to get creative.
Summary
The title property on QMenu is meant for menu bar display, not for context menu headings. To show a visible title on a popup menu, you have three options:
addSection()— built-in but only visible with certain styles (like Fusion).- Disabled action — simple but looks like a grayed-out menu item.
QWidgetActionwith aQLabel— looks like a heading and gives you full control over the title's appearance.
Usually QWidgetAction is the one you want to go with. For more on building menus, toolbars, and actions in PyQt6, see our tutorial on Actions, Toolbars & Menus in PyQt6. If you're building custom widgets like styled labels or other UI elements, you may also find our guide to creating your own custom widgets in PyQt6 helpful.