一段时间以来,我一直在为此苦苦挣扎,甚至我不确定自己使用的是正确的pyqt类。
我有一个QTableView,它显示2d整数数组,我希望对其进行过滤以仅显示一个值下的整数。
这是示例:
from PyQt4 import QtCore, QtGui
import random
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
super(TableModel, self).__init__(parent)
self._columns = 3
self._parent = parent
def rowCount(self, parent=QtCore.QModelIndex()):
return int( float( len( self._parent.data ) ) / float( self._columns ) )+1
def columnCount(self, parent=QtCore.QModelIndex()):
return self._columns
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
if role == QtCore.Qt.DisplayRole:
try:
value = self._parent.data[ index.row() * self._columns + index.column() ]
except:
pass
else:
return value
return None
class tableProxyModel(QtGui.QSortFilterProxyModel):
def __init__(self, parent=None):
super(tableProxyModel, self).__init__(parent)
self._parent = parent
self.filterColumn = []
self.filterRow = []
self.maxFilter =0
def setFilter(self, value):
#
# this will find the 2d position of the datas that need to be kept visible
# we need a list of the row and column axis
#
self.maxFilter = value
self.filterColumn = []
self.filterRow = []
for i in self._parent.data:
if i < self.maxFilter:
positionInList = [j for j,x in enumerate( self._parent.data ) if x == i][0]
filterRow, filterColumn = self.getPosition( positionInList )
self.filterColumn.append(filterColumn)
self.filterRow.append(filterRow)
self.invalidateFilter()
def getPosition(self, value):
#
# convert data list to a 2d array
#
leftOver = value%self._parent._tm._columns
filterRow = (value-leftOver) / self._parent._tm._columns
filterColumn = leftOver
return filterRow, filterColumn
def filterAcceptsRow(self, row, parent):
model = self.sourceModel()
if row in self.filterRow:
return True
else:
return False
def filterAcceptsColumn(self, column, parent):
model = self.sourceModel()
if column in self.filterColumn:
return True
else:
return False
if __name__=="__main__":
from sys import argv, exit
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.data = [ d for d in range(10) ]
###################################################
## this line shuffle the list, if you quote this line and keep the list in order , then the example works as expected
random.shuffle(self.data)
print self.data
l=QtGui.QVBoxLayout( self )
self._tm=TableModel( self )
self._tv=QtGui.QTableView( )
self._tpm=tableProxyModel( self )
self._tpm.setSourceModel( self._tm )
self._tv.setModel( self._tpm )
l.addWidget( self._tv )
#################################################
## apply the filter, only show numbers under 5
self._tpm.setFilter(5)
a=QtGui.QApplication(argv)
w=Widget()
w.show()
w.raise_()
exit(a.exec_())
如果执行此示例,则可以看到它不仅显示了5 ...以下的值。
如何过滤填充有随机值的QTableView?我希望在这里使用模型/视图系统。
答案 0 :(得分:0)
QSortFilterProxyModel
仅过滤列或行,不过滤元素,因此这种情况的策略是将表转换为列表,然后过滤列表,因为过滤行等同于过滤元素,并且最终将列表转换成表格。
import random
import math
from PyQt4 import QtCore, QtGui
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, columns, parent=None):
super(TableModel, self).__init__(parent)
self._columns = columns
self._data = data[:]
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid() or self._columns == 0:
return 0
return math.ceil(len(self._data )*1.0/self._columns)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._columns
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return
if role == QtCore.Qt.DisplayRole:
try:
value = self._data[ index.row() * self._columns + index.column() ]
return value
except:
pass
class Table2ListProxyModel(QtGui.QIdentityProxyModel):
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self.sourceModel().rowCount() * self.sourceModel().columnCount()
def mapFromSource(self, sourceIndex):
if sourceIndex.isValid() and sourceIndex.column() == 0 \
and sourceIndex.row() < self.rowCount():
r = sourceIndex.row()
c = sourceIndex.column()
row = c * sourceIndex.model().columnCount() + r
return self.index(row, 0)
return QtCore.QModelIndex()
def mapToSource(self, proxyIndex):
r = proxyIndex.row() / self.sourceModel().columnCount()
c = proxyIndex.row() % self.sourceModel().columnCount()
return self.sourceModel().index(r, c)
def index(self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column)
class ListFilterProxyModel(QtGui.QSortFilterProxyModel):
def setThreshold(self, value):
setattr(self, "threshold", value)
self.invalidateFilter()
def filterAcceptsRow(self, row, parent):
if hasattr(self, "threshold"):
ix = self.sourceModel().index(row, 0)
val = ix.data()
if val is None:
return False
return val < getattr(self, "threshold")
return True
class List2TableProxyModel(QtGui.QIdentityProxyModel):
def __init__(self, columns=1, parent=None):
super(List2TableProxyModel, self).__init__(parent)
self._columns = columns
def columnCount(self, parent=QtCore.QModelIndex()):
return self._columns
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return math.ceil(self.sourceModel().rowCount()/self._columns)
def index(self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column)
def data(self, index, role=QtCore.Qt.DisplayRole):
r = index.row()
c = index.column()
row = r * self.columnCount() + c
if row < self.sourceModel().rowCount():
return super(List2TableProxyModel, self).data(index, role)
def mapFromSource(self, sourceIndex):
r = math.ceil(sourceIndex.row() / self.columnCount())
c = sourceIndex.row() % self.columnCount()
return self.index(r, c)
def mapToSource(self, proxyIndex):
if proxyIndex.isValid():
r = proxyIndex.row()
c = proxyIndex.column()
row = r * self.columnCount() + c
return self.sourceModel().index(row, 0)
return QtCore.QModelIndex()
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
data = [random.choice(range(10)) for i in range(20)]
l = QtGui.QHBoxLayout(self)
splitter = QtGui.QSplitter()
l.addWidget(splitter)
tv = QtGui.QTableView()
lv = QtGui.QListView()
lvf = QtGui.QListView()
tvf = QtGui.QTableView()
model = TableModel(data, 3, self)
proxy1 = Table2ListProxyModel(self)
proxy1.setSourceModel(model)
proxy2 = ListFilterProxyModel(self)
proxy2.setSourceModel(proxy1)
proxy2.setThreshold(5)
proxy3 = List2TableProxyModel(3, self)
proxy3.setSourceModel(proxy2)
tv.setModel(model)
lv.setModel(proxy1)
lvf.setModel(proxy2)
tvf.setModel(proxy3)
splitter.addWidget(tv)
splitter.addWidget(lv)
splitter.addWidget(lvf)
splitter.addWidget(tvf)
if __name__=="__main__":
import sys
a=QtGui.QApplication(sys.argv)
w=Widget()
w.show()
sys.exit(a.exec_())