The code below creates a window with QListView
(left) and QTableView
(right). Both Views share the same data model.
QListView
lists the dictionary keys such as 'Animals','Fish' and 'Birds'. 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. Every mouse click performed on a left-side QListView triggers onClick()
function. 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.
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. 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:
value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)
where value is a dictionary such as:
{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.
Accodring to your code:
If data
is called with index(1,0)
it returns Animals
.
If data
is called with index(1,1)
it returns Animals
.
If data
is called with index(1,2)
it returns Animals
.
Instead it should be
If data
is called with index(1,0)
it returns Animals
.
If data
is called with index(1,1)
it returns Bison
.
If data
is called with index(1,2)
it returns Panther
.
If data
is called with index(1,3)
it returns Elephant
.
Totally 4 columns.
To hide the first column which is a group name from the table view use hideColumn(0)
.
ps. ItemDataRole
is a enum name not a value.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.