Why QToolTips Won’t Appear on QActions in QMenu (PySide GUI Troubleshooting & Fix)

PySide (now part of Qt for Python) is a powerful framework for building cross-platform graphical user interfaces (GUIs). One of its most useful features is QToolTip, which displays small, context-sensitive hints when users hover over widgets. However, a common frustration among developers is that tooltips set on QAction objects often fail to appear when those actions are added to a QMenu—even though they work perfectly when the same actions are added to a QToolBar.

This blog dives into why this issue occurs, walks through troubleshooting steps to confirm the problem, and provides a reliable fix to make QToolTip work with QAction in QMenu. Whether you’re building a desktop app with menus, toolbars, or both, this guide will help you ensure tooltips behave consistently across your UI.

Table of Contents#

  1. Understanding QToolTips and QActions
  2. The Problem: Why ToolTips Fail on QActions in QMenus
  3. Troubleshooting Steps: Isolate the Issue
  4. The Fix: Making QToolTips Appear on QActions in QMenus
  5. Alternative Approaches
  6. Conclusion
  7. References

1. Understanding QToolTips and QActions#

Before diving into the problem, let’s clarify the roles of QToolTip and QAction in PySide:

What is QToolTip?#

QToolTip is a static class in PySide that displays short, temporary hints when the user hovers the mouse over a widget. Tooltips are set using the setToolTip(str) method on widgets (e.g., QPushButton, QToolButton). For example:

button = QPushButton("Click Me")  
button.setToolTip("This button does something awesome!")  # Hover to see this  

What is QAction?#

QAction is a non-visual object that represents an action the user can trigger (e.g., "Open", "Save", "Cut"). It encapsulates properties like text, icons, shortcuts, and tooltips. QAction can be added to multiple UI elements, such as QMenu (dropdown menus), QToolBar (toolbars), or QWidget (as context menu actions).

A QAction has its own toolTip property, set via setToolTip(str), which should display when the user hovers over the action—but only in certain contexts.

The Confusion: Tooltips in Toolbars vs. Menus#

Here’s where developers often get stuck:

  • When a QAction is added to a QToolBar, its tooltip works as expected: hover over the toolbar button, and the tooltip appears.
  • When the same QAction is added to a QMenu, the tooltip does not appear when hovering over the menu item.

This inconsistency is the root of the problem.

2. The Problem: Why ToolTips Fail on QActions in QMenus#

To understand why tooltips don’t work for QAction in QMenu, we need to dig into how QMenu renders and handles events for its actions.

Key Reasons:#

1. QMenu Prioritizes Action Text Over Tooltips#

QMenu is designed to display action text, shortcuts, and icons prominently. By default, it does not allocate space or logic to render tooltips for menu items. Tooltips are considered secondary here, as menus are intended for quick selection, not detailed context.

2. Event Handling Differences Between Menus and Toolbars#

  • In QToolBar, each QAction is represented by a QToolButton, which is a widget that natively supports QToolTip (via setToolTip). Hover events on the button trigger the tooltip.
  • In QMenu, QAction is rendered as a menu item (not a widget). QMenu uses a QListView-like internal view to display items, and this view does not propagate hover events to the QAction in a way that triggers tooltips by default.

3. Qt’s Design Intent#

Qt’s documentation subtly hints that QAction tooltips are primarily intended for toolbars, where space is limited, and tooltips provide quick context. Menus, with more visible text, are not expected to need tooltips.

Proof of the Issue#

To confirm, run this minimal example. The action will show a tooltip in the toolbar but not in the menu:

import sys  
from PySide6.QtWidgets import (QApplication, QMainWindow, QToolBar, QMenu, QAction)  
 
class MainWindow(QMainWindow):  
    def __init__(self):  
        super().__init__()  
        self.setWindowTitle("QAction Tooltip Test")  
 
        # Create an action with a tooltip  
        self.my_action = QAction("My Action", self)  
        self.my_action.setToolTip("This tooltip works in toolbars, but not menus!")  # Tooltip  
 
        # Add action to a toolbar (tooltip works here)  
        toolbar = QToolBar("My Toolbar")  
        toolbar.addAction(self.my_action)  
        self.addToolBar(toolbar)  
 
        # Add action to a menu (tooltip does NOT work here)  
        menu = self.menuBar().addMenu("My Menu")  
        menu.addAction(self.my_action)  
 
if __name__ == "__main__":  
    app = QApplication(sys.argv)  
    window = MainWindow()  
    window.show()  
    sys.exit(app.exec())  

Run this code:

  • Hover over the toolbar button: tooltip appears.
  • Open "My Menu" and hover over "My Action": no tooltip.

3. Troubleshooting Steps#

Before applying the fix, confirm the issue isn’t caused by a simple mistake. Use these steps to isolate the problem:

Step 1: Verify setToolTip is Called Correctly#

Ensure you’re calling my_action.setToolTip("Your tooltip") and that the tooltip text is not empty. Typos like setToolTips (plural) or missing calls are common.

Step 2: Test the Action in a Toolbar#

As shown in the example above, add the action to a QToolBar. If the tooltip works there, the issue is specific to QMenu, not the action itself.

Step 3: Check for Event Filters or Styles Blocking Tooltips#

If you’re using custom event filters or styles (e.g., QProxyStyle), they might accidentally block tooltip events. Temporarily remove these to see if tooltips reappear.

Step 4: Ensure the Menu is Properly Populated#

Confirm the action is added to the menu with menu.addAction(my_action). A common mistake is forgetting to add the action to the menu entirely.

If all steps confirm the tooltip works in toolbars but not menus, you’re facing the core issue—and need a custom fix.

4. The Fix: Making QToolTips Appear on QActions in QMenus#

The solution involves subclassing QMenu and overriding its event handling to manually show tooltips when hovering over menu items. Here’s how:

Core Idea#

QMenu emits QEvent.ToolTip events when the mouse hovers over its items. By subclassing QMenu and overriding the event method, we can:

  1. Detect QEvent.ToolTip events.
  2. Find the QAction under the hover position.
  3. Manually show the action’s tooltip using QToolTip.showText().

Step-by-Step Implementation#

1. Subclass QMenu#

Create a custom QMenu subclass (e.g., TooltipMenu) and override the event method to handle tooltip events.

2. Override event to Detect Hover#

In the event method:

  • Check if the event is a QEvent.ToolTip (hover event).
  • Get the hover position relative to the menu.
  • Use actionAt(pos) to find the QAction under the cursor.
  • If the action has a tooltip, show it with QToolTip.showText().

3. Use the Custom Menu in Your App#

Replace the default QMenu with your TooltipMenu subclass when creating menus.

Full Working Example#

import sys  
from PySide6.QtWidgets import (QApplication, QMainWindow, QToolBar, QMenu, QAction)  
from PySide6.QtCore import QEvent, QPoint  
 
class TooltipMenu(QMenu):  
    """Custom QMenu subclass to show tooltips for QActions."""  
    def event(self, event: QEvent) -> bool:  
        # Check if the event is a ToolTip event (hover)  
        if event.type() == QEvent.ToolTip:  
            # Get the hover position relative to the menu  
            pos = event.pos()  
            # Find the QAction under the hover position  
            action = self.actionAt(pos)  
 
            if action and action.toolTip():  
                # Show the tooltip at the global hover position  
                global_pos = self.mapToGlobal(pos)  
                QToolTip.showText(global_pos, action.toolTip(), self)  
            else:  
                # Hide tooltip if no action or no tooltip  
                QToolTip.hideText()  
            return True  # We handled the event  
 
        # Let the base class handle other events  
        return super().event(event)  
 
class MainWindow(QMainWindow):  
    def __init__(self):  
        super().__init__()  
        self.setWindowTitle("Fixed: QAction Tooltips in QMenu")  
 
        # Create an action with a tooltip  
        self.my_action = QAction("My Action", self)  
        self.my_action.setToolTip("Now this tooltip works in menus AND toolbars!")  
 
        # Add action to a toolbar (tooltip works here by default)  
        toolbar = QToolBar("My Toolbar")  
        toolbar.addAction(self.my_action)  
        self.addToolBar(toolbar)  
 
        # Add action to OUR CUSTOM TooltipMenu (tooltip now works!)  
        menu = TooltipMenu("My Menu", self)  # Use custom menu  
        menu.addAction(self.my_action)  
        self.menuBar().addMenu(menu)  
 
if __name__ == "__main__":  
    app = QApplication(sys.argv)  
    window = MainWindow()  
    window.show()  
    sys.exit(app.exec())  

How It Works:#

  • TooltipMenu overrides event to catch QEvent.ToolTip events.
  • actionAt(pos) finds the QAction under the hover position in the menu.
  • QToolTip.showText(global_pos, tooltip, self) displays the tooltip at the global cursor position, anchored to the menu.

5. Alternative Approaches#

If subclassing QMenu feels heavy, consider these alternatives:

1. Use QProxyStyle#

Qt styles control widget rendering. You can override QProxyStyle to modify how QMenu handles tooltips. This is more complex but useful if you need to apply the fix globally across all menus.

2. Use QWidgetAction#

Wrap the QAction in a QWidgetAction (a widget-based action) and add a custom widget (e.g., QLabel) with a tooltip. This works but adds overhead, as QWidgetAction is heavier than a standard QAction.

3. Status Bar Hints#

Instead of tooltips, use QAction’s statusTip property to show hints in the status bar when hovering over menu items. This is Qt’s recommended alternative for menus.

6. Conclusion#

Tooltips failing to appear for QAction in QMenu is a common PySide pitfall, rooted in Qt’s design choices for menus vs. toolbars. The fix—subclassing QMenu to manually handle hover events and show tooltips—is reliable and lightweight.

By using TooltipMenu (the custom subclass), you ensure tooltips work consistently for QAction in both menus and toolbars, improving UX for your app.

7. References#