python - 如何过滤子项,QTreeView使用QSortFilterProxyModel

标签 python python-3.x pyqt pyqt5 qsortfilterproxymodel

我希望能够过滤“参数”列下的每个项目。我正在使用 QSortFilterProxyModel 和 QLineEdit 尝试从 QTreeView 中过滤掉特定级别,但是我无法过滤除“根级别”之外的任何级别/子级别。

如何修复此实现,以便能够过滤任何级别而不仅仅是“RootLevel”?

from PyQt5 import QtGui,QtCore,QtWidgets
import sys

class MainFrame(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)

        tree = {'RootLevel':{
                    "Level1": {"Level1_item1":14, "Level1_item2":12, "Level1_item3":3.55},
                    "Level2": {
                        "Level2_SubLevel1": {"Level2_SubLevel1_item1":3.52, "Level2_SubLevel1_item2":2.55, "Level2_SubLevel1_item3":13},
                        "Level2_SubLevel2": {"Level2_SubLevel2_item1":2, "Level2_SubLevel2_item2":4, "Level2_SubLevel2_item3":3.11}
                        },
                    "Level3": {"Level3_item1":12, "Level3_item2":13.55, "Level3_item3":122}}
        }

        self.tree = QtWidgets.QTreeView(self)
        self.filterEdit = QtWidgets.QLineEdit()
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.filterEdit)
        layout.addWidget(self.tree)

        self.root_model = QtGui.QStandardItemModel()
        self.root_model.setHorizontalHeaderLabels(['Level','Values'])

        self.fill_model_from_json(self.root_model.invisibleRootItem(), tree)

        self.proxyModel = QtCore.QSortFilterProxyModel(self)
        self.proxyModel.setSourceModel(self.root_model)

        self.tree.setModel(self.proxyModel)
        self.tree.header().setMinimumSectionSize(300)
        self.filterEdit.textChanged.connect(self.onTextChanged)

    @QtCore.pyqtSlot(str)
    def onTextChanged(self, text):
        self.proxyModel.setFilterRegExp(text)

    def fill_model_from_json(self, parent, d):
        if isinstance(d, dict):
            for key, value in d.items():
                it = QtGui.QStandardItem(str(key))
                if isinstance(value, dict):
                    parent.appendRow(it)
                    self.fill_model_from_json(it, value)
                else:
                    it2 = QtGui.QStandardItem(str(value))
                    parent.appendRow([it, it2])

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main = MainFrame()
    main.show()
    sys.exit(app.exec_())

最佳答案

如果要过滤第二列,则必须使用 filterKeyColumn 设置它属性,如果您想在较低级别进行过滤,则必须启用 recursiveFilteringEnabled属性,建议您使用expandAll()展开所有项目。以便过滤可见。

from PyQt5 import QtGui, QtCore, QtWidgets


class MainFrame(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        tree = {
            "RootLevel": {
                "Level1": {
                    "Level1_item1": 14,
                    "Level1_item2": 12,
                    "Level1_item3": 3.55,
                },
                "Level2": {
                    "Level2_SubLevel1": {
                        "Level2_SubLevel1_item1": 3.52,
                        "Level2_SubLevel1_item2": 2.55,
                        "Level2_SubLevel1_item3": 13,
                    },
                    "Level2_SubLevel2": {
                        "Level2_SubLevel2_item1": 2,
                        "Level2_SubLevel2_item2": 4,
                        "Level2_SubLevel2_item3": 3.11,
                    },
                },
                "Level3": {
                    "Level3_item1": 12,
                    "Level3_item2": 13.55,
                    "Level3_item3": 122,
                },
            }
        }

        self.tree = QtWidgets.QTreeView()
        self.filterEdit = QtWidgets.QLineEdit(textChanged=self.onTextChanged)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.filterEdit)
        layout.addWidget(self.tree)

        self.root_model = QtGui.QStandardItemModel()
        self.root_model.setHorizontalHeaderLabels(["Level", "Values"])

        self.fill_model_from_json(self.root_model.invisibleRootItem(), tree)

        self.proxyModel = QtCore.QSortFilterProxyModel(
            self, filterKeyColumn=1, recursiveFilteringEnabled=True
        )
        self.proxyModel.setSourceModel(self.root_model)

        self.tree.setModel(self.proxyModel)
        self.tree.header().setMinimumSectionSize(300)

        self.tree.expandAll()
        self.resize(640, 480)

    @QtCore.pyqtSlot(str)
    def onTextChanged(self, text):
        self.proxyModel.setFilterRegExp(text)

    def fill_model_from_json(self, parent, d):
        if isinstance(d, dict):
            for key, value in d.items():
                it = QtGui.QStandardItem(str(key))
                if isinstance(value, dict):
                    parent.appendRow(it)
                    self.fill_model_from_json(it, value)
                else:
                    it2 = QtGui.QStandardItem(str(value))
                    parent.appendRow([it, it2])


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    main = MainFrame()
    main.show()
    sys.exit(app.exec_())

enter image description here

关于python - 如何过滤子项,QTreeView使用QSortFilterProxyModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57153891/

相关文章:

python - 如何查找 Mechanize (python)发布的 POST 或 GET 变量

python - Django 从另一个进程访问数据库

python - 替换重复的字符串,但在安装点

python-3.x - Pandas:如何获取数据帧第一行和最后一行的键(索引)

python - PyQt:QTableWidget 取消全选?

python - 格式化字符串的问题 - Python 2.7.3

python - 无法使用 popen 启动两个交互式 shell

python-3.x - PyCharm 单元测试 : AttributeError: module 'enum' has no attribute 'IntFlag'

python - 如何设置PyQt5 Qtimer以指定的时间间隔更新?

python - 如何将 QCompleter 与 InputDialog 一起使用?