我有一个“嵌套”的2层qmenus,在其中创建了用于重命名和删除的上下文菜单。
我为QMenus创建了一个子类,希望使代码更整洁,因为我无法在当前代码中使用eventFilter
,因为它弄乱了某些功能。
对于重命名部分,虽然它重命名了第一层项目,但是当我尝试对第二层项目执行相同操作时,提示实际上重命名了第一层项目。
以下是我执行的QMenu子类的代码部分,如果您执行以下操作,则该代码部分:
main
的新对象main
中,创建另一个名为sub
的对象main
并选择rename
选项,并将其更改为'newMain',则可以使用sub
上的重命名为newSub
newMain
更改为newSub
,而sub
保持不变。有人可以向我的QMenu子类说明我做错了什么吗?
import functools
import sys
from PyQt4 import QtGui, QtCore
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 QRenameAction(QtGui.QAction):
def __init__(self, icon=None, text="Rename Item", parent=None):
if icon:
super(QRenameAction, self).__init__(icon, text, parent)
else:
super(QRenameAction, self).__init__(text, parent)
class QDeleteAction(QtGui.QAction):
def __init__(self, icon=None, text="Delete Item", parent=None):
if icon:
super(QDeleteAction, self).__init__(icon, text, parent)
else:
super(QDeleteAction, 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 setup_menu(self):
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
no_right_click = [QAddAction, QRenameAction, QDeleteAction]
if any([isinstance(self.actionAt(event.pos()), instance) for instance in no_right_click]):
return
self.show_adv_qmenu()
def show_adv_qmenu(self):
qmenu = QCustomMenu(self)
rename_menu_action = QRenameAction(text= "Rename Item", parent=self)
rename_slot = functools.partial(self.rename_menu_item)
rename_menu_action.triggered.connect(rename_slot)
qmenu.addAction(rename_menu_action)
delete_menu_action = QDeleteAction(text="Delete Item", parent=self)
delete_slot = functools.partial(self.delete_menu_item, delete_menu_action)
delete_menu_action.triggered.connect(delete_slot)
qmenu.addAction(delete_menu_action)
qmenu.exec_(QtGui.QCursor().pos())
def addAction(self, action):
super(QCustomMenu, self).addAction(action)
def rename_menu_item(self):
new_name, ok = QtGui.QInputDialog.getText(
self,
"Rename Menu Item ({0})".format(self.title()),
"New name:"
)
if ok:
self.setTitle(new_name)
def delete_menu_item(self, action):
reply = QtGui.QMessageBox.question(self, 'Message',
"Really Delete this item?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
parent = action.parent()
print parent
self.remove_menu_item(self)
else:
event.ignore()
def err_popup(self):
"""Prompts a notification popup."""
msg = QtGui.QMessageBox()
msg.setIcon(QtGui.QMessageBox.Critical)
msg.setText("Input name already exists. Please check.")
msg.setWindowTitle('Unable to add item')
msg.setStandardButtons(QtGui.QMessageBox.Ok)
msg.exec_()
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 new 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):
base_qmenu = QCustomMenu(title=main_menu_name, parent=self)
base_qmenu.setTearOffEnabled(True)
add_item_action = QAddAction(None, 'Add Item', base_qmenu)
slot = functools.partial(self.add_sub_item, base_qmenu)
add_item_action.triggered.connect(slot)
base_qmenu.addAction(add_item_action)
self.qmenu.addMenu(base_qmenu)
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 = QtGui.QAction(sub_menu_name, self)
slot = functools.partial(
self._callActionItem,
str(base_menu.title()),
str(sub_menu_name)
)
action.setCheckable(True)
action.setChecked(True)
action.toggled.connect(slot)
base_menu.addAction(action)
def _callActionItem(self):
pass
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = Example()
window.show()
sys.exit(app.exec_())