【问题标题】:Getting Maximum Recursion Error when trying to override QTreeView.edit()尝试覆盖 QTreeView.edit() 时出现最大递归错误
【发布时间】:2020-01-21 15:54:39
【问题描述】:

标题说明了大部分内容。我必须在这里做一些愚蠢的事情,但是由于某种原因,当我右键单击 Treeview 时,无论何时我尝试覆盖 QTreeView 的编辑功能,都会出现最大递归深度错误。

这特别是当我尝试调用超级的编辑功能时。这是问题的一个例子。我在这里搞砸了什么?

from PyQt5 import QtWidgets, QtGui, QtCore


class EditTreeView(QtWidgets.QTreeView):

    editingRequested = QtCore.pyqtSignal(QtCore.QModelIndex)

    def __init__(self, parent=None):
        super(EditTreeView, self).__init__(parent)

    def edit(self, index, QAbstractItemView_EditTrigger=None, QEvent=None):
        super(EditTreeView, self).edit(index)


class testTreeview(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(testTreeview, self).__init__(parent)
        self.mainTree = EditTreeView()
        self.lo = QtWidgets.QVBoxLayout()
        self.lo.addWidget(self.mainTree)
        self.setLayout(self.lo)
        self.model = QtGui.QStandardItemModel()
        self.mainTree.setModel(self.model)

    def populate(self):
        row = [QtGui.QStandardItem('teststuff'), ]
        root = self.model.invisibleRootItem()
        root.appendRow(row)


if __name__ == "__main__":
    from PyQt5 import QtCore, QtGui, QtWidgets

    app = QtWidgets.QApplication([])
    volume = testTreeview()
    volume.show()
    app.exec_()

【问题讨论】:

    标签: python pyqt pyqt5 qtreeview


    【解决方案1】:

    说明:

    QTreeView 继承自 QAbstractItemView,如果查看该类的方法,可以看到有 2 个方法同名:

    bool QAbstractItemView::edit(const QModelIndex &index, QAbstractItemView::EditTrigger trigger, QEvent *event)

    在索引处开始编辑项目,必要时创建编辑器,并且 如果视图的状态现在是 EditingState,则返回 true;否则 返回 false。

    导致编辑过程的动作由触发器描述, 并且关联的事件由事件指定。

    可以通过指定触发器来强制编辑 QAbstractItemView::AllEditTriggers。


    void QAbstractItemView::edit(const QModelIndex &index)

    开始编辑与给定索引对应的项目,如果它是 可编辑。

    请注意,此函数不会更改当前索引。由于 当前索引定义要编辑的下一个和上一个项目,用户可以 发现键盘导航无法按预期工作。提供 一致的导航行为,在此之前调用 setCurrentIndex() 具有相同模型索引的函数。

    据观察,第一种方法比第二种方法更通用,因此我们怀疑第二种方法将使用第一种方法,如果审查the source code,确实会发生这种情况:

    void QAbstractItemView::edit(const QModelIndex & index)
    {
        Q_D(QAbstractItemView);
        if (Q_UNLIKELY(!d->isIndexIsValid(index)))
            qWarning("edit: index was invalid");
        if (Q_UNLIKELY(!edit(index, AllEditTriggers, 0)))
            qWarning("edit: editing failed");
    }

    所以在你的情况下清楚地解释错误:你正在覆盖第一个方法并调用第二个,但第二个根据源代码使用第一个,并返回无限循环。


    解决方案

    解决方案是对所有参数使用相同方法的super:

    class EditTreeView(QtWidgets.QTreeView):
        editingRequested = QtCore.pyqtSignal(QtCore.QModelIndex)
    
        def edit(self, index, trigger, event):
            self.editingRequested.emit(index)
            return super(EditTreeView, self).edit(index, trigger, event)
    

    但请记住,覆盖是关于第一个方法,在 C++ 中允许有同名的方法,但在 python 中,如果有多个同名的方法,最后一个将删除以前的方法。

    【讨论】:

    • 谢谢。看来你最近解决了我所有的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 2018-12-03
    • 2018-06-08
    相关资源
    最近更新 更多