链接的QSortFilterProxyModels [英] Chained QSortFilterProxyModels

查看:89
本文介绍了链接的QSortFilterProxyModels的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一个存储10,000个字符串实体的列表变量datalist. QTableView仅需要显示其中一些实体.这就是为什么为QTableView分配了QSortFilterProxyModel进行所有过滤的原因. 在完成所有代理工作之后,QTableView接收"要显示的25个实体(因此剩余的9,975个实体被过滤掉".

Let's say I have a list variable datalist storing 10,000 string entities. The QTableView needs to display only some of these entities. That's is why QTableView was assigned QSortFilterProxyModel that does all the filtering. After all Proxy work is completed the QTableView "receives" 25 entities to display (so remaining 9,975 entities were "filtered out".

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

Now, I create a QLineEdit to be used as a search field where the user can type a keyword to narrow down the list of the displayed 25 entities (items) even further. For this purpose I link QLineEdit's textChanged signal to assigned to QTableView Proxy's filterAcceptsRow() method.

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

The problem I see here is that Proxy model needs to get back to the original 10,000 entities long list to re-filter once again. And again. And again.

我想知道是否有可能创建第二个代理来替代第一个代理已滤除的内容:25个实体,而不是10,000个.

I wonder if it is possible to create a second Proxy that would pickup what the first Proxy has already filtered out: 25 entities instead of 10,000.

因此生成的模式如下所示:

So the resulting schema would look like this:

datalist> QAbstractTableModel> QSortFilterProxyModel> QSortFilterProxyModel> QTableView

位置:

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

datalist is 10,000 entities long list variable.

QAbstractTableModel是基础数据模型

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

QSortFilterProxyModel is a first Proxy Model doing the dirtiest and slowest filtering job

QSortFilterProxyModel是第二个代理模型,用于处理由第一个代理数据(用于通过用户的关键字进行过滤)预先过滤的数据.

QSortFilterProxyModel is a second Proxy Model working on a pre-filtered by first Proxy data (it is used to filter by the user's keyword).

QTableView是QTableView本身,用于显示实体项目.

QTableView is a QTableView itself used to display the entity items.

所以,问题是:这是一个有效的主意吗?

So, the question is: is it a valid idea?

推荐答案

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

The code below uses two ProxyModels filtering 10,000 items. It works...

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_())

这里是单个代理方法.与两个代理的实现相比,按关键字搜索的速度明显慢:

Here is a single Proxy approach. Searching by keyword is noticably slower vs two proxys implementation:

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_()) 

这篇关于链接的QSortFilterProxyModels的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆