如何使用QSortFilterProxyModel过滤子项,QTreeView

How to filter sub-items, QTreeView using QSortFilterProxyModel

我希望能够过滤 'Parameter' 列下的每个项目。我正在使用 QSortFilterProxyModel 和 QLineEdit 来尝试从 QTreeView 中过滤掉特定级别,但是我无法过滤掉除 'Rootlevel' 之外的任何 level/sublevel。

如何修复此实现以能够过滤任何级别而不仅仅是 '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 property, if you want to filter at lower levels then you must enable the recursiveFilteringEnabled property, and it is recommended that you expand all the items using 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_())