簡體   English   中英

如何在 PyQt5/PySide2 中實現可過濾列表?

[英]How to implement a filterable List in PyQt5/PySide2?

如何在 PyQt5/PySide2 中實現一個簡單的可過濾列表?

測試代碼:

import sys

from PySide2.QtCore import QAbstractListModel
from PySide2.QtGui import Qt
from PySide2.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QListView


class MyModel(QAbstractListModel):
    def __init__(self):
        QAbstractListModel.__init__(self)
        self.test_data = ['Test','abc', 'Test2', 'aaa', 'bbb']
        self.filtered_data = self.test_data
        self.filter = ''
        self.refresh()

    def refresh(self):
        if self.filter:
            self.filtered_data  = [x for x in self.test_data if self.filter in x]
        else:
            self.filtered_data = self.test_data

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self.filtered_data[index.row()]

    def rowCount(self, index):
        return len(self.filtered_data)


def text_changed():
    model.filter = le.text()
    model.refresh()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()

    le = QLineEdit()
    le.textChanged.connect(text_changed)
    model = MyModel()
    lv = QListView(model=model)

    layout = QVBoxLayout()
    layout.addWidget(le)
    layout.addWidget(lv)

    window.setLayout(layout)
    window.show()
    app.exec_()


Filter 本身可以工作,但 ListView 沒有正確刷新。 當我更改過濾器時,列表不會更新,直到我用鼠標移動到一個條目。

您更改內部列表的信息並不會立即通知某些更改,對於每種類型的更改,必須在更改之前或之后調用某些方法。

在這種情況下, beginResetModel 和 endResetModel 就足夠了

def refresh(self):
    self.beginResetModel()
    if self.filter:
        self.filtered_data  = [x for x in self.test_data if self.filter in x]
    else:
        self.filtered_data = self.test_data
    self.endResetModel()

相反,另一個更優雅的解決方案是使用 QSortFilterProxyModel:

class MyModel(QAbstractListModel):
    def __init__(self):
        QAbstractListModel.__init__(self)
        self.test_data = ['Test','abc', 'Test2', 'aaa', 'bbb']
        self.filtered_data = self.test_data

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self.filtered_data[index.row()]

    def rowCount(self, index):
        return len(self.filtered_data)


def text_changed():
    proxy.filter = le.text()


class SortFilterProxyModel(QSortFilterProxyModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._filter = ""
    def filterAcceptsRow(self, sourceRow, sourceParent):
        index = self.sourceModel().index(sourceRow, 0, sourceParent)
        if self.filter:
            return self.filter in index.data()
        return True

    @property
    def filter(self):
        return self._filter
    
    @filter.setter
    def filter(self, f):
        self._filter = f
        self.invalidateFilter()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()

    le = QLineEdit()
    le.textChanged.connect(text_changed)
    model = MyModel()
    proxy = SortFilterProxyModel()
    proxy.setSourceModel(model)
    lv = QListView(model=proxy)

    layout = QVBoxLayout()
    layout.addWidget(le)
    layout.addWidget(lv)

    window.setLayout(layout)
    window.show()
    app.exec_()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM