链式 QSortFilterProxyModel

Posted

技术标签:

【中文标题】链式 QSortFilterProxyModel【英文标题】:Chained QSortFilterProxyModels 【发布时间】:2015-01-16 00:42:47 【问题描述】:

假设我有一个列表变量 datalist 存储 10,000 个字符串实体。 QTableView 只需要显示其中一些实体。这就是为什么QTableView 被分配QSortFilterProxyModel 来完成所有过滤的原因。 完成所有代理工作后,QTableView“接收”25 个要显示的实体(因此剩余的 9,975 个实体被“过滤掉”。

现在,我创建了一个QLineEdit 用作搜索字段,用户可以在其中键入关键字以进一步缩小显示的 25 个实体(项目)的列表。为此,我将QLineEdittextChanged 信号链接到分配给QTableView 代理的filterAcceptsRow() 方法。

我在这里看到的问题是代理模型需要回到原来的 10,000 个实体长列表才能再次重新过滤。然后再次。又一次。

我想知道是否可以创建第二个代理来获取第一个代理已经过滤掉的内容:25 个实体而不是 10,000 个。

因此生成的架构将如下所示:

datalist > QAbstractTableModel > QSortFilterProxyModel > QSortFilterProxyModel > QTableView

地点:

datalist 是 10,000 个实体长列表变量。

QAbstractTableModel 是基础数据模型

QSortFilterProxyModel 是第一个执行最脏和最慢过滤工作的代理模型

QSortFilterProxyModel 是第二个代理模型,工作于由第一个代理数据预先过滤的数据(它用于按用户的关键字过滤)。

QTableView 是一个 QTableView 本身,用于显示实体项。

所以,问题是:这是一个有效的想法吗?

【问题讨论】:

天真,因为QSortFilterProxyModel.setSourceModel(model) 期望传入的模型是QAbstractItemModel 的子类,而QSortFilterProxyModel QAbstractItemModel 的子类,你的想法至少应该运行没有错误。我不确定你是否得到了你正在寻找的加速。绝对值得组装一个最小的测试示例并尝试一下! 【参考方案1】:

下面的代码使用两个 ProxyModel 过滤 10,000 个项目。有用...

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class MyTableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = [i for i in range(10000)]

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid():
            return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        column=index.column()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

class Proxy01(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy01, self).__init__()
    def filterAcceptsRow(self, row, parent):        
        sourceModel=self.sourceModel()
        index=sourceModel.index(row, 0, parent)
        name=sourceModel.data(index, Qt.DisplayRole).toString()

        if name and not int(name)%10:
            return True
        return False

class Proxy02(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy02, self).__init__()
        self.keyword=None

    def setKeyword(self, arg):
        if arg: self.keyword=str(arg)
        self.reset()    

    def filterAcceptsRow(self, row, parent):
        sourceModel=self.sourceModel().sourceModel()
        index=sourceModel.index(row, 0, parent)
        name=sourceModel.data(index, Qt.DisplayRole).toString()

        if self.keyword and name and not self.keyword.lower() in str(name).lower():
            return False        
        return True

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=MyTableModel(self)               

        self.proxy1=Proxy01()
        self.proxy1.setSourceModel(self.tablemodel)

        self.proxy2=Proxy02()
        self.proxy2.setSourceModel(self.proxy1)

        tableviewA=QTableView() 
        tableviewA.setModel(self.proxy2)

        searchEdit=QLineEdit()
        searchEdit.textChanged.connect(self.proxy2.setKeyword)

        layout = QVBoxLayout(self)
        layout.addWidget(tableviewA)
        layout.addWidget(searchEdit)
        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

这是一个单一的代理方法。与两个代理实现相比,按关键字搜索要慢得多:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class MyTableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = [i for i in range(10000)]

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid():
            return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        column=index.column()
        if row<len(self.items):
            return QVariant(self.items[row])
        else:
            return QVariant()

class Proxy01(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy01, self).__init__()
        self.keyword=None

    def setKeyword(self, arg):
        if arg: self.keyword=str(arg)
        self.reset()    

    def filterAcceptsRow(self, row, parent):
        sourceModel=self.sourceModel()
        index=sourceModel.index(row, 0, parent)
        name=sourceModel.data(index, Qt.DisplayRole).toString()

        if self.keyword and name and not self.keyword.lower() in str(name).lower():
            return False        
        return True

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=MyTableModel(self)               

        self.proxy1=Proxy01()
        self.proxy1.setSourceModel(self.tablemodel)

        tableviewA=QTableView() 
        tableviewA.setModel(self.proxy1)

        searchEdit=QLineEdit()
        searchEdit.textChanged.connect(self.proxy1.setKeyword)

        layout = QVBoxLayout(self)
        layout.addWidget(tableviewA)
        layout.addWidget(searchEdit)
        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_()) 

【讨论】:

以上是关于链式 QSortFilterProxyModel的主要内容,如果未能解决你的问题,请参考以下文章

求1个C++链式链表的程序

Android之链式调用(方法链)

线性表---链式存储(双向链表)

线性表---链式存储(双向链表)

链式存储结构之静态链表

Problem D: 逆置链式链表(线性表)