嵌套QMenus中的上下文菜单重命名

2024-05-16 11:37:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个“嵌套的”,一个两层的qmenus,我在其中创建了一个用于重命名和删除的上下文菜单。 我为QMenus创建了一个子类,希望使我的代码更干净,因为我无法在当前代码中使用eventFilter,因为它会破坏一些功能。。你知道吗

对于重命名部分,虽然它重命名了第一层,但当我尝试对第二层的项执行相同的操作时,提示实际上重命名了第一层的项。你知道吗

以下是我完成的QMenu子类的代码部分,如果您执行以下操作:

  • 右键单击并添加一个名为main的新对象
  • main中,创建另一个名为sub的对象
  • (这是一个额外的右键单击)如果您在main上执行另一次鼠标右键单击并选择rename选项,并将其更改为“newMain”,则此操作有效
  • 执行第3点中详细说明的相同操作,但这次将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_())

Tags: textnameselfnoneaddinitdefaction