Qt中QAction绑定QIcon后复选框不可见,如何同时显示两者?
Absolutely! You can definitely show both the icon and checkmark for your checkable QActions in a QMenu. The problem you're running into is that Qt's default style hides the check indicator when an action has an icon—instead, it typically uses the icon's state to signal if the action is checked. But if you want both elements visible, here are two reliable ways to make it happen:
Method 1: Use QWidgetAction for Custom Menu Items
This approach lets you build a custom widget that includes both the icon and a checkbox, giving you full control over the layout and behavior.
from PyQt5 import QtWidgets, QtGui, QtCore import sys class window21(QtWidgets.QMainWindow): def __init__(self): super(window21,self).__init__() # Helper function to create checkable actions with icon and visible checkbox def create_checkable_action(text, icon_path=None): widget_action = QtWidgets.QWidgetAction(self) # Set up a horizontal layout for the custom widget layout = QtWidgets.QHBoxLayout() layout.setContentsMargins(4, 2, 4, 2) layout.setSpacing(8) # Add checkbox with the action text checkbox = QtWidgets.QCheckBox(text) checkbox.setCheckable(True) # Add icon if a path is provided if icon_path: icon_label = QtWidgets.QLabel() icon_label.setPixmap(QtGui.QPixmap(icon_path).scaled(16, 16, QtCore.Qt.KeepAspectRatio)) layout.addWidget(icon_label) layout.addWidget(checkbox) # Wrap the layout in a container widget container = QtWidgets.QWidget() container.setLayout(layout) widget_action.setDefaultWidget(container) # Sync checkbox state with the action's checked state def sync_action_state(state): widget_action.setChecked(state == QtCore.Qt.Checked) checkbox.stateChanged.connect(sync_action_state) return widget_action # Create your actions using the helper function self.newAction = create_checkable_action("&New", ":/im/new.png") self.openAction = create_checkable_action("&Open") self.printAction = create_checkable_action("&Print") self.quitAction = create_checkable_action("&Quit") self.saveAction = create_checkable_action("&Save") self.groupMenu = QtWidgets.QMenu("nested menu", self) self.groupAction = QtWidgets.QActionGroup(self) myMenu = self.menuBar() file = myMenu.addMenu("&File") # Add custom actions to the File menu file.addAction(self.newAction) file.addAction(self.openAction) file.addAction(self.printAction) # Set up exclusive action group for nested menu self.groupAction.addAction(self.quitAction) self.groupAction.addAction(self.saveAction) self.groupAction.setExclusive(True) # Sync action group selection with checkboxes def sync_group_selection(selected_action): for action in self.groupAction.actions(): checkbox = action.defaultWidget().findChild(QtWidgets.QCheckBox) checkbox.setChecked(action == selected_action) self.groupAction.triggered.connect(sync_group_selection) for j in self.groupAction.actions(): self.groupMenu.addAction(j) file.addMenu(self.groupMenu) self.show() app = QtWidgets.QApplication([]) ex = window21() sys.exit(app.exec_())
Method 2: Tweak the QMenu's Stylesheet
If you prefer a simpler fix without custom widgets, you can force the check indicator to appear even when an action has an icon by adjusting the menu's stylesheet.
Add this line right after creating your file menu:
file.setStyleSheet(""" QMenu::item { padding-left: 28px; /* Add space to the left for the check indicator */ } QMenu::indicator { left: 6px; width: 16px; height: 16px; /* Optional: Customize the indicator appearance */ /* image: url(:/check-icon.png); */ } """)
This stylesheet adjusts the padding to make room for the checkmark and ensures the indicator is visible regardless of whether the action has an icon. Note that stylesheet behavior can vary slightly across platforms, but this works consistently for most desktop environments.
Why This Happens
Qt's default styles (like Fusion, Windows, or macOS) hide the check indicator when an action has an icon because they assume you'll use a different icon state (e.g., a highlighted or checked version of the icon) to indicate the action's status. But if you want both the icon and the checkmark visible, the methods above will solve that problem.
内容的提问来源于stack exchange,提问作者Nimish Bansal

