【问题标题】:PyQt extend existing Contextual Menu when editing QstandardItem's Text (in a QtreeView)PyQt 在编辑 QstandardItem 的文本时扩展现有的上下文菜单(在 QtreeView 中)
【发布时间】:2015-11-10 05:57:55
【问题描述】:

我想在编辑 QStandardItem 的文本时显示的“默认”上下文菜单中添加一个操作(在 QTreeView 中显示)

这个上下文菜单似乎是 QPlainTextEdit 小部件的默认上下文菜单。有默认操作:撤消、重做、复制、粘贴、删除、全选。我想在这里添加一个自定义操作。

我不知道如何修改这个菜单。

提前致谢!

【问题讨论】:

    标签: pyqt contextmenu qtreeview qstandarditem


    【解决方案1】:

    要为 QTreeView 单元格自定义编辑器,您需要创建一个 QItemDelegate 并将其与树视图的列相关联。

    自定义委托可能更复杂(例如更改编辑器的保存/恢复行为),但在这种情况下,我们只想更改它用于实例化编辑器小部件的类:

    class CustomDelegate(QItemDelegate):
        def createEditor(self, parent, option, index):
            editor = CustomLineEdit(parent)                
            return editor
    

    这将确保编辑器现在是一个CustomLineEdit 小部件,它可以具有您希望的任何附加功能(如自定义上下文菜单)。在下面的示例中,我使用Achayan 提供的答案的略微修改版本来实现此CustomLineEdit。

    您使用以下代码将自定义委托分配给列(在本例中,我选择了树视图的第 0 列):

    # Create custom Delegate which instantiates our custom editor
    delegate = CustomDelegate()
    # Set this delegate for the first column only
    treeview.setItemDelegateForColumn(0, delegate)
    

    完整代码

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    class CustomLineEdit(QLineEdit):
        def __init__(self, *args, **kwargs):
            super(CustomLineEdit, self).__init__(*args, **kwargs)
            self.setContextMenuPolicy(Qt.CustomContextMenu)
            self.customContextMenuRequested.connect(self.__contextMenu)
    
        def __contextMenu(self):
            self._normalMenu = self.createStandardContextMenu()
            self._addCustomMenuItems(self._normalMenu)
            self._normalMenu.exec_(QCursor.pos())
    
        def _addCustomMenuItems(self, menu):
            menu.addSeparator()
            menu.addAction(u'Test', self.testFunc)
    
        def testFunc(self):
            print "Call"
    
    
    class CustomDelegate(QItemDelegate):
        def createEditor(self, parent, option, index):
            editor = CustomLineEdit(parent)                
            return editor
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        # Create Widgets
        window = QMainWindow()
        widget = QWidget()
        layout = QVBoxLayout(widget)
        treeview = QTreeView()
        layout.addWidget(treeview)
        window.setCentralWidget(widget)
        window.show()
    
        # Create Model
        model = QStandardItemModel()
        model.setHorizontalHeaderLabels(['Header 1','Header 2'])
        treeview.setModel(model)
    
        # Create custom Delegate which instantiates our custom editor
        delegate = CustomDelegate()
        # Set this delegate for the first column only
        treeview.setItemDelegateForColumn(0, delegate)
    
        # Populate the model with some test data
        row1 = []
        row1.append(QStandardItem("asd"))
        row1.append(QStandardItem("fgh"))
        model.appendRow(row1)
        row2 = []
        row2.append(QStandardItem("qwe"))
        row2.append(QStandardItem("rty"))
        model.appendRow(row2)
    
        app.exec_()
    

    【讨论】:

    • 非常感谢您准确而有启发性的回答@three_pineapples!这正是我正在寻找的。你今天帮了我很多 :) 我刚刚修改了你的代码,而且效果很好。
    • @Glyphosate 如果这回答了您的问题,请单击左侧的勾号将其标记为已接受的答案。一旦您拥有足够的声誉,您还可以对任何您认为有帮助的答案进行投票。
    【解决方案2】:

    我有一个 QPlainTextEdit 的例子。您可以根据需要进行修改。希望这会有所帮助

    class CustomLineEdit(QtGui.QPlainTextEdit):
        def __init__(self, parent = None):
            super(CustomLineEdit, self).__init__()
            self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
            self.customContextMenuRequested.connect(self.__contextMenu)
    
        def __contextMenu(self):
            self._normalMenu = self.createStandardContextMenu()
            self._addCustomMenuItems(self._normalMenu)
            self._normalMenu.exec_(QtGui.QCursor.pos())
    
        def _addCustomMenuItems(self, menu):
            menu.addSeparator()
            menu.addAction(u'Test', self.testFunc)
    
        def testFunc(self):
            print "Call"
    
    class mainwindow(QtGui.QWidget):
        def __init__(self , parent = None):
            super(mainwindow, self).__init__()    
            self.setupgui()
        def setupgui(self):
    
            self.resize(800,600)
            self.setWindowTitle('test')
            newLayout = QtGui.QHBoxLayout()
            qlbl = CustomLineEdit()
            newLayout.addWidget(qlbl)
            self.setLayout(newLayout)
            self.show()
    
    
    def main():
    
        app = QtGui.QApplication(sys.argv)
        ex = mainwindow()
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 为什么有人反对这个?如果您投反对票,请告诉我代码有什么问题。
    • 如果我不得不猜测,是因为这不能回答问题吗? OP 希望在编辑 QTreeView 中的单元格时执行此操作。告诉他们“调整这段代码”不一定有帮助。
    • 调整代码看起来很简单:你只需要继承QStandardItem而不是QPlainTextEdit。其余的没有改变,对吧?这个答案对我很有帮助。
    • 感谢您的回答 Achayan。我可以将自定义操作添加到我自己的小部件的标准菜单中。但我的问题是关于 QTreeView/QStandardItem 的行为中包含的小部件的上下文菜单。
    • @tmoreau :如果您将 QstandardItem 子类化,您可以在右键单击时创建/修改上下文菜单。但是,这不是您编辑 QStandardItem 的名称(文本)时显示的自定义菜单。
    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多