简体   繁体   English

QSortFilterProxyModel如何工作

[英]How QSortFilterProxyModel works

The code below creates a window with QListView (left) and QTableView (right). 下面的代码使用QListView (左)和QTableView (右)创建一个窗口。 Both Views share the same data model. 两个视图共享相同的数据模型。

QListView lists the dictionary keys such as 'Animals','Fish' and 'Birds'. QListView列出字典键,例如“动物”,“鱼”和“鸟”。 When a left-side view's 'Animals' item is clicked a right-side view should display: a first column: 'Bison', a second column: 'Panther' and third: 'Elephant'. 单击左侧视图的“动物”项时,应显示右侧视图:第一列:“野牛”,第二列:“豹”,第三列:“大象”。

To address this goal there was QSortFilterProxyModel assigned to right-side QTableView to filter its context. 为了实现此目标,将QSortFilterProxyModel分配给右侧QTableView来过滤其上下文。 Every mouse click performed on a left-side QListView triggers onClick() function. 在左侧QListView上执行的每次鼠标单击都会触发onClick()函数。 This function checks what the left-side view's current item is. 此功能检查左侧视图的当前项目。 Then it queries the name of the key and a key's corresponding value from self.modelDict dictionary. 然后,它从self.modelDict字典中查询键的名称和键的对应值。

Here is a window screenshot: 这是一个窗口截图: 在此处输入图片说明

Apparently the code doesn't do what it is supposed to. 显然,代码没有执行应有的功能。 QSortFilterProxyModel does indeed display a correct "item"... so both views are in sync. QSortFilterProxyModel确实显示了正确的“项目” ...因此两个视图是同步的。 That's good. 那很好。 But the right-side-table view is displaying the same key name in every column: "Animals","Animals","Animals". 但是右侧表视图在每列中显示相同的键名称:“动物”,“动物”,“动物”。 While the goal once again is to display the list of the animals themselves taken from a dictionary received from .data() method: 目标是再次显示从.data()方法接收的词典中提取的动物本身的列表:

value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)

where value is a dictionary such as: 其中value是一个字典,例如:

{1:'Bison',2:'Panther',3:'Elephant'}

Please advise. 请指教。

import os,sys
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}

class DataModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.modelDict={}    
        self.items=[]    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)   
    def columnCount(self, index=QtCore.QModelIndex()):
        return 3
    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
        if role==QtCore.Qt.DisplayRole: return self.items[index.row()]
        if role==QtCore.Qt.ItemDataRole: return self.modelDict.get(str(index.data().toString()))

    def addItem(self, itemName=None, column=0):
        totalItems=self.rowCount()+1
        self.beginInsertRows(QtCore.QModelIndex(), totalItems, column)
        if not itemName:            itemName='Item %s'%self.rowCount()
        self.items.append(itemName)
        self.endInsertRows()

    def buildItems(self):
        for key in self.modelDict:
            index=QtCore.QModelIndex()
            self.addItem(key) 

class ProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self, parent=None):
        super(ProxyModel, self).__init__(parent)

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout)   

        self.dataModel=DataModel()
        self.dataModel.modelDict=elements
        self.dataModel.buildItems() 

        self.proxyModel=ProxyModel()
        self.proxyModel.setFilterKeyColumn(0)    
        self.proxyModel.setSourceModel(self.dataModel)

        self.viewA=QtGui.QListView()
        self.viewA.setModel(self.dataModel)
        self.viewA.clicked.connect(self.onClick)          
        self.viewB=QtGui.QTableView() 
        self.viewB.setModel(self.proxyModel)

        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.viewB)    
        self.show()

    def onClick(self):
        index=self.viewA.currentIndex()
        key=self.dataModel.data(index, QtCore.Qt.DisplayRole)  
        value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)        
        self.proxyModel.setFilterRegExp('%s'%key)
        print 'onClick(): key: %s'%type('%s'%key)

window=Window()
sys.exit(app.exec_())

DisplayRole should return different data for different rows. DisplayRole应该为不同的行返回不同的数据。
Accodring to your code: 根据您的代码:

If data is called with index(1,0) it returns Animals . 如果使用index(1,0)调用data ,则返回Animals
If data is called with index(1,1) it returns Animals . 如果使用index(1,1)调用data ,则返回Animals
If data is called with index(1,2) it returns Animals . 如果使用index(1,2)调用data ,则返回Animals

Instead it should be 相反,它应该是

If data is called with index(1,0) it returns Animals . 如果使用index(1,0)调用data ,则返回Animals
If data is called with index(1,1) it returns Bison . 如果使用index(1,1)调用data ,则返回Bison
If data is called with index(1,2) it returns Panther . 如果使用index(1,2)调用data ,则返回Panther
If data is called with index(1,3) it returns Elephant . 如果使用index(1,3)调用data ,则返回Elephant
Totally 4 columns. 共4列。

To hide the first column which is a group name from the table view use hideColumn(0) . 要从表视图中隐藏作为组名的第一列,请使用hideColumn(0)

ps. PS。 ItemDataRole is a enum name not a value. ItemDataRole是枚举名称,而不是值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM