ленивая фильтрация QTreeview с помощью QsortFIlterProxymodel

Я хочу расширить вопрос, который я задал ранее, с помощью фильтра. В моем предыдущем вопросе мне помогли отложить загрузку древовидной структуры, сначала родители и только добавив дочерние элементы родителя, когда пользователь нажимает на узел более или менее следующим образом

from PyQt4 import QtGui


class Widget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.mytreeview = QtGui.QTreeView(self)
        self.setLayout(QtGui.QVBoxLayout())
        self.layout().addWidget(self.mytreeview)
        self.model = QtGui.QStandardItemModel(self.mytreeview)
        self.mytreeview.setModel(self.model)
        self.mytreeview.clicked.connect(self.update_model)
        self.initialise_model()

    def initialise_model(self):
        for text in ["parent1", "parent2", "parent3"]:
            item = QtGui.QStandardItem(text)
            self.model.appendRow(item)

    def update_model(self, index):
        parent = self.model.itemFromIndex(index)
        for text in ["children1", "children2", "children3"]:
            children = QtGui.QStandardItem("{}_{}".format(parent.text(), text))
            parent.appendRow(children)
        self.mytreeview.expand(index)

Теперь я хочу расширить и использовать фильтр для древовидного представления, чтобы пользователь мог ввести имя родительского узла, и древовидное представление отфильтровало бы себя до соответствующих соответствующих узлов. Я по-прежнему хочу, чтобы пользователь мог щелкать родительский узел, и даже после фильтрации дочерние узлы будут добавлены к родительскому узлу.

Как я могу адаптировать для этого следующее? Я установил древовидное представление следующим образом

proxyModel = QSortFilterProxyModel(treeView)
proxyModel.setSourceModel(self.model)

# set model
treeView.setModel(proxyModel);   
treeView.setSortingEnabled(true)

def update_model(self, index):
    parent = self.model.itemFromIndex(index)
    ##not sure about this now in the light of the proxyModel
    for text in ["children1", "children2", "children3"]:
        children = QtGui.QStandardItem("{}_{}".format(parent.text(), text))
        parent.appendRow(children)
    self.mytreeview.expand(index)#not sure about this either as the index is of the proxyModel

У меня есть два основных вопроса: во-первых, индекс proxyModel и индекс исходной модели, я не уверен, как это работает, а также при расширении щелчка по узлу,


person Man Wa kileleshwa    schedule 21.10.2017    source источник


Ответы (1)


Классы, которые наследуются от QAbstractProxyModel как QSortFilterProxyModel, имеют метод mapToSource(), который возвращает индекс исходной модели, передавая индекс модели прокси, также имеет другой метод, называемый mapFromSource(), который выполняет обратное, поэтому вы должны использовать этот метод, чтобы иметь возможность добавлять предметы к правильной модели.

Чтобы отфильтровать данные, я добавил QLineEdit, где подключен сигнал textChanged, текст, который предоставляет сигнал, который мы использовали для фильтра.

class Widget(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.filterLe = QtGui.QLineEdit(self)
        self.mytreeview = QtGui.QTreeView(self)
        self.setLayout(QtGui.QVBoxLayout())
        self.layout().addWidget(self.filterLe)
        self.layout().addWidget(self.mytreeview)
        self.model = QtGui.QStandardItemModel(self.mytreeview)

        self.proxyModel = QtGui.QSortFilterProxyModel(self.mytreeview)
        self.proxyModel.setSourceModel(self.model)
        self.mytreeview.setSortingEnabled(True)

        # set model
        self.mytreeview.setModel(self.proxyModel)
        self.mytreeview.clicked.connect(self.update_model)
        self.filterLe.textChanged.connect(self.onTextChanged)
        self.initialise_model()

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

    def initialise_model(self):
        for text in ["parent1", "parent2", "parent3"]:
            item = QtGui.QStandardItem(text)
            self.model.appendRow(item)

    def update_model(self, index):
        ix = self.proxyModel.mapToSource(index)
        parent = self.model.itemFromIndex(ix)
        for text in ["children1", "children2", "children3"]:
            children = QtGui.QStandardItem("{}_{}".format(parent.text(), text))
            parent.appendRow(children)
        self.mytreeview.expand(index)
person eyllanesc    schedule 21.10.2017
comment
он работает с дочерними элементами? Я использую тот же подход, но по какой-то причине, когда я ввожу имя дочернего элемента в поле поиска, он не найден, но родительский элемент в порядке - person Sergey Maslov; 20.05.2018
comment
@SergeyMaslov QSortFilterProxyModel работает только для родителей, если вы хотите выполнить рекурсивную фильтрацию, используйте recursiveFilteringEnabled doc.qt.io/qt-5/, но он доступен только из PyQt 5.10 - person eyllanesc; 20.05.2018