Reputation: 19329
The code below creates a window with two views: QListView
on a left and QTreeView
on a right. Both views share the same Model()
which sub-classed from QAbstractTableModel
.
I want left QListView
to display the self.modelDict
dictionary keys. While the right-side QTreeView
to display the dictionary values. I have been recommended to use QSortFilterProxyModel
to get things done. I would appreciate if you show how to implement QSortFilterProxyModel
into this code:
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 Model(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()]
def addItem(self, itemName=None, column=0):
totalItems=self.rowCount()
self.beginInsertRows(QtCore.QModelIndex(), totalItems+1, column)
if not itemName: itemName='Item %s'%self.rowCount()
self.items.append(itemName)
self.endInsertRows()
def buildItems(self):
(self.addItem(key) for key in self.modelDict)
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
mainLayout=QtGui.QHBoxLayout()
self.setLayout(mainLayout)
self.model=Model()
self.model.modelDict=elements
self.model.buildItems()
self.viewA=QtGui.QListView()
self.viewA.setModel(self.model)
self.viewB=QtGui.QTableView()
self.viewB.setModel(self.model)
mainLayout.addWidget(self.viewA)
mainLayout.addWidget(self.viewB)
self.show()
window=Window()
sys.exit(app.exec_())
Upvotes: 1
Views: 1563
Reputation: 4344
Create QSortFilterProxyModel
:
self.proxy = QSortFilterProxyModel()
Assign a base model to the proxy:
self.proxy.setSourceModel(self.model)
Make the proxy filter use the first column of the model:
self.proxy.setFilterKeyColumn(0)
Assign the proxy to the table instead of the model:
self.viewB.setModel(self.proxy)
When current index in the first view is changed (connect to signal activated
), change the filter key:
self.proxy.setFilterRegExp(self.model.data(self.viewA.currentIndex()).toString())
viewB
will display data filtered by the value of an item selected in viewA
Also
data
in the model. It never returns values, only keys. self.items
also contains only keys.Depending on how do you want to display values - in 3 rows 1 column or in 3 columns 1 row - these should be fixed.
For example, if you want to display values in 1 row 3 columns, you need to have something like this in your data
method:
if role==QtCore.Qt.DisplayRole: return self.items[index.row()][index.column()]
Upvotes: 4