使用 QSortFilterProxyModel 对 QTableView 进行排序后保留选择

Keep the selection after using QSortFilterProxyModel to sort a QTableView

我发现了一个类似的问题。 Keep the selection after filtering a QTableView with a QSortFilterProxyModel 但是是关于C++ QT的,我自己试了很多次,还是没在PyQt5或者PySide6中搞定?

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QTableView, QHeaderView, QVBoxLayout
from PyQt5.QtCore import Qt, QSortFilterProxyModel
from PyQt5.QtGui import QStandardItemModel, QStandardItem

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(1200, 1000)
        mainLayout = QVBoxLayout()

        # companies = ('Apple', 'Facebook', 'Google', 'Amazon', 'Walmart', 'Dropbox', 'Starbucks', 'eBay', 'Canon')
        companies = [f'company_{i}' for i in range(200)]
        model = QStandardItemModel(len(companies), 1)
        model.setHorizontalHeaderLabels(['Company'])

        for row, company in enumerate(companies):
            item = QStandardItem(company)
            model.setItem(row, 0, item)

        filter_proxy_model = QSortFilterProxyModel()
        filter_proxy_model.setSourceModel(model)
        filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        filter_proxy_model.setFilterKeyColumn(0)

        search_field = QLineEdit()          
        search_field.textChanged.connect(filter_proxy_model.setFilterRegExp)
        mainLayout.addWidget(search_field)

        table = QTableView()
        table.setStyleSheet('font-size: 35px;')
        table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        table.setModel(filter_proxy_model)
        mainLayout.addWidget(table)

        self.setLayout(mainLayout)

app = QApplication(sys.argv)
demo = AppDemo()
demo.show()
sys.exit(app.exec_()) 

 

我自己找到了解决办法。我改为使用 QListWidget。但同样的逻辑也可以应用于 QListView。下面是代码。

下面是核心部分,是一个slot,接一个line edit。这样做,效率很好,特别是当你有很多项目时,因为当 lineedit 输入更改时它不使用 QListWidget.clear(),它只是将项目隐藏在幕后。

# deal with search file
    def onFileTextChanged(self, text):
        search_items = self.listWidget.findItems(text, Qt.MatchContains)

        for index in range(self.listWidget.count()):
            item = self.listWidget.item(index)
            if item in search_items:
                item.setHidden(False)
            else:
                item.setHidden(True)