У меня есть вложенные пункты меню, в которых я пытаюсь сделать все элементы доступными для проверки. Первоначально переключение не работает для основного элемента (QMenu, установленного как QAction), но работает для подэлементов.
Но при использовании mousePressEvent
переключение теперь работает для основного элемента, но не для подэлементов.
Пытался воспроизвести то, что я сделал для основного элемента для функции подэлемента, но переключение по-прежнему не работает. И похоже, он вызывается дважды в файле _callActionItem()
.
Однако по некоторым причинам, если окно подэлемента находится в режиме отрыва, переключение возможно, но не так, если вы делаете контекстное меню в самом инструменте.
Кроме того, если я отключу mousePressEvent
в QCustomMenu
, я вернусь к исходной точке, где переключение работает для подэлементов, но не для основных элементов.
class QSubAction(QtGui.QAction):
def __init__(self, text="", parent=None):
super(QSubAction, self).__init__(text, parent)
self.setCheckable(True)
self.setChecked(True)
class QAddAction(QtGui.QAction):
def __init__(self, icon=None, text="Add Item", parent=None):
if icon:
super(QAddAction, self).__init__(icon, text, parent)
else:
super(QAddAction, self).__init__(text, parent)
class QCustomMenu(QtGui.QMenu):
"""Customized QMenu."""
def __init__(self, title, parent=None):
super(QCustomMenu, self).__init__(title=str(title), parent=parent)
self.setup_menu()
def mousePressEvent(self, event):
action = self.activeAction()
if isinstance(action, QtGui.QAction):
action.trigger()
return QtGui.QMenu.mousePressEvent(self, event)
def setup_menu(self):
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
no_right_click = [QAddAction]
if any([isinstance(self.actionAt(event.pos()), instance) for instance in no_right_click]):
return
pos = event.pos()
def addAction(self, action):
super(QCustomMenu, self).addAction(action)
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Context menu')
self.qmenu = QCustomMenu(title='', parent=self)
add_item_action = QtGui.QAction('Add Main item', self,
triggered=self.add_new_item)
self.qmenu.addAction(add_item_action)
def contextMenuEvent(self, event):
action = self.qmenu.exec_(self.mapToGlobal(event.pos()))
def add_new_item(self):
main_menu_name, ok = QtGui.QInputDialog.getText(
self,
'Main Menu',
'Name of new Menu Item:'
)
if ok:
self._addMenuItemTest(main_menu_name)
def _addMenuItemTest(self, main_menu_name):
icon_path = '/user_data/add.png'
base_qmenu = QCustomMenu(title=main_menu_name, parent=self)
base_qmenu.setTearOffEnabled(True)
add_item_action = QAddAction(None, 'Add Sub Item', base_qmenu)
slot = functools.partial(self.add_sub_item, base_qmenu)
add_item_action.triggered.connect(slot)
base_qmenu.addAction(add_item_action)
test_action = QtGui.QAction(main_menu_name, self)
test_action.setMenu(base_qmenu)
test_action.setCheckable(True)
test_action.setChecked(True)
self.connect(
test_action,
QtCore.SIGNAL("triggered(bool)"),
self.main_toggling
)
self.qmenu.addAction(test_action)
def main_toggling(self, check_state):
sender_obj = self.sender()
if isinstance(sender_obj, QtGui.QAction):
sender_obj.setChecked(check_state)
def add_sub_item(self, base_menu):
sub_menu_name, ok = QtGui.QInputDialog.getText(
self,
'Sub Menu',
'Name of new Sub Item:'
)
if ok:
action = QSubAction(sub_menu_name, self)
slot = functools.partial(
self._callActionItem,
action
)
# action.toggled.connect(slot)
# from pprint import pprint
# pprint(help(action))
# action.connect(action, QtCore.SIGNAL("triggered(bool)"), self._callActionItem)
base_menu.addAction(action)
def _callActionItem(self, action):
# This is called twice, False and True again
print '>>> sub check-state : ', action.isChecked()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = Example()
window.show()
sys.exit(app.exec_())