如何使用QSortFilterProxyModel做数据聚合
How to use QSortFilterProxyModel to do data aggregation
我使用 QSortFilterProxyModel 来过滤模型数据并将其显示在 tableView 中。
然后我想聚合过滤后的数据,所以我新建了一个tableView2来显示过滤后的数据聚合。
我新建了一个QSortFilterProxyModel来聚合数据,但是不知道如何获取源数据,然后增加数据
但以我目前对QSortFilterProxyModel的了解,我似乎无从下手。
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
class FilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, headers):
super(FilterProxyModel, self).__init__(parent=None)
self._headers = headers
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
if self.columnCount() < section+1:
return QtCore.QVariant()
else:
return self._headers[section]
return super().headerData(section, orientation, role)
def data(self, index, role=None):
if role == Qt.DisplayRole:
if index.row() < 1:
return 1
else:
return QtCore.QVariant()
def rowCount(self, parent=None, *args, **kwargs):
return 1
def columnCount(self, parent=None, *args, **kwargs):
return len(self._headers)
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, datas):
super(TableModel, self).__init__()
self._datas = datas
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return self._datas[index.row()][index.column()]
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self._datas)
def columnCount(self, parent=QtCore.QModelIndex()):
if self._datas:
return len(self._datas[0])
else:
return 0
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.datas = [('a1', 'b1', 'c'), ('a2', 'b1', 'c'), ('a3', 'b1', 'c'), ('a4', 'b1', 'c')]*25
self.model = TableModel(self.datas)
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setFilterRegExp(QtCore.QRegExp('a1|a3'))
self.proxy_model.setFilterKeyColumn(0)
self.proxy_model2 = FilterProxyModel(['a1', 'a3'])
self.proxy_model2.setSourceModel(self.model)
self.proxy_model2.setFilterRegExp(QtCore.QRegExp('a1|a3'))
self.proxy_model2.setFilterKeyColumn(0)
self.treeview = QtWidgets.QTableView()
self.treeview.setModel(self.proxy_model)
self.treeview2 = QtWidgets.QTableView()
self.treeview2.setModel(self.proxy_model2)
layout = QtWidgets.QVBoxLayout(self)
hlayout = QtWidgets.QHBoxLayout()
hlayout.addWidget(self.treeview)
hlayout.addWidget(self.treeview2)
layout.addLayout(hlayout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main = MainWidget()
main.show()
sys.exit(app.exec_())
这是我要实现的根据指定的head key(a1,a3)进行数据聚合的效果:
代理模型用于映射项目,但在这种情况下,目标是计数,所以使用代理模型对我来说似乎没有必要。相反,使用 match()
来计算和连接指示模型中某些变化的信号以重新计算它会更容易。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, datas):
super(TableModel, self).__init__()
self._datas = datas
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
return self._datas[index.row()][index.column()]
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self._datas)
def columnCount(self, parent=QtCore.QModelIndex()):
if self._datas:
return len(self._datas[0])
else:
return 0
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.datas = [
("a1", "b1", "c"),
("a2", "b1", "c"),
("a3", "b1", "c"),
("a4", "b1", "c"),
] * 25
self.model = TableModel(self.datas)
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setFilterRegExp(QtCore.QRegExp("a1|a3"))
self.proxy_model.setFilterKeyColumn(0)
self.model2 = QtGui.QStandardItemModel()
self.model2.setHorizontalHeaderLabels(["a1", "a3"])
self.view1 = QtWidgets.QTableView()
self.view1.setModel(self.proxy_model)
self.view2 = QtWidgets.QTableView()
self.view2.setModel(self.model2)
layout = QtWidgets.QVBoxLayout(self)
hlayout = QtWidgets.QHBoxLayout()
hlayout.addWidget(self.view1)
hlayout.addWidget(self.view2)
layout.addLayout(hlayout)
self.model.dataChanged.connect(self.update_model2)
self.model.rowsInserted.connect(self.update_model2)
self.model.rowsRemoved.connect(self.update_model2)
self.model.columnsInserted.connect(self.update_model2)
self.model.columnsRemoved.connect(self.update_model2)
self.model.modelReset.connect(self.update_model2)
self.update_model2()
def update_model2(self):
self.model2.setRowCount(0)
column = 0
for i in range(self.model2.columnCount()):
header_item = self.model2.horizontalHeaderItem(i)
if header_item is None:
return
text = header_item.text()
indexes = self.model.match(
self.model.index(0, column),
QtCore.Qt.DisplayRole,
text,
hits=-1,
flags=QtCore.Qt.MatchExactly,
)
item = QtGui.QStandardItem()
item.setData(len(indexes), QtCore.Qt.DisplayRole)
self.model2.setItem(0, i, item)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main = MainWidget()
main.show()
sys.exit(app.exec_())
我使用 QSortFilterProxyModel 来过滤模型数据并将其显示在 tableView 中。 然后我想聚合过滤后的数据,所以我新建了一个tableView2来显示过滤后的数据聚合。
我新建了一个QSortFilterProxyModel来聚合数据,但是不知道如何获取源数据,然后增加数据
但以我目前对QSortFilterProxyModel的了解,我似乎无从下手。
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
class FilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, headers):
super(FilterProxyModel, self).__init__(parent=None)
self._headers = headers
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
if self.columnCount() < section+1:
return QtCore.QVariant()
else:
return self._headers[section]
return super().headerData(section, orientation, role)
def data(self, index, role=None):
if role == Qt.DisplayRole:
if index.row() < 1:
return 1
else:
return QtCore.QVariant()
def rowCount(self, parent=None, *args, **kwargs):
return 1
def columnCount(self, parent=None, *args, **kwargs):
return len(self._headers)
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, datas):
super(TableModel, self).__init__()
self._datas = datas
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return self._datas[index.row()][index.column()]
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self._datas)
def columnCount(self, parent=QtCore.QModelIndex()):
if self._datas:
return len(self._datas[0])
else:
return 0
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.datas = [('a1', 'b1', 'c'), ('a2', 'b1', 'c'), ('a3', 'b1', 'c'), ('a4', 'b1', 'c')]*25
self.model = TableModel(self.datas)
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setFilterRegExp(QtCore.QRegExp('a1|a3'))
self.proxy_model.setFilterKeyColumn(0)
self.proxy_model2 = FilterProxyModel(['a1', 'a3'])
self.proxy_model2.setSourceModel(self.model)
self.proxy_model2.setFilterRegExp(QtCore.QRegExp('a1|a3'))
self.proxy_model2.setFilterKeyColumn(0)
self.treeview = QtWidgets.QTableView()
self.treeview.setModel(self.proxy_model)
self.treeview2 = QtWidgets.QTableView()
self.treeview2.setModel(self.proxy_model2)
layout = QtWidgets.QVBoxLayout(self)
hlayout = QtWidgets.QHBoxLayout()
hlayout.addWidget(self.treeview)
hlayout.addWidget(self.treeview2)
layout.addLayout(hlayout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main = MainWidget()
main.show()
sys.exit(app.exec_())
这是我要实现的根据指定的head key(a1,a3)进行数据聚合的效果:
代理模型用于映射项目,但在这种情况下,目标是计数,所以使用代理模型对我来说似乎没有必要。相反,使用 match()
来计算和连接指示模型中某些变化的信号以重新计算它会更容易。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, datas):
super(TableModel, self).__init__()
self._datas = datas
def data(self, index, role=QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
return self._datas[index.row()][index.column()]
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self._datas)
def columnCount(self, parent=QtCore.QModelIndex()):
if self._datas:
return len(self._datas[0])
else:
return 0
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.datas = [
("a1", "b1", "c"),
("a2", "b1", "c"),
("a3", "b1", "c"),
("a4", "b1", "c"),
] * 25
self.model = TableModel(self.datas)
self.proxy_model = QtCore.QSortFilterProxyModel()
self.proxy_model.setSourceModel(self.model)
self.proxy_model.setFilterRegExp(QtCore.QRegExp("a1|a3"))
self.proxy_model.setFilterKeyColumn(0)
self.model2 = QtGui.QStandardItemModel()
self.model2.setHorizontalHeaderLabels(["a1", "a3"])
self.view1 = QtWidgets.QTableView()
self.view1.setModel(self.proxy_model)
self.view2 = QtWidgets.QTableView()
self.view2.setModel(self.model2)
layout = QtWidgets.QVBoxLayout(self)
hlayout = QtWidgets.QHBoxLayout()
hlayout.addWidget(self.view1)
hlayout.addWidget(self.view2)
layout.addLayout(hlayout)
self.model.dataChanged.connect(self.update_model2)
self.model.rowsInserted.connect(self.update_model2)
self.model.rowsRemoved.connect(self.update_model2)
self.model.columnsInserted.connect(self.update_model2)
self.model.columnsRemoved.connect(self.update_model2)
self.model.modelReset.connect(self.update_model2)
self.update_model2()
def update_model2(self):
self.model2.setRowCount(0)
column = 0
for i in range(self.model2.columnCount()):
header_item = self.model2.horizontalHeaderItem(i)
if header_item is None:
return
text = header_item.text()
indexes = self.model.match(
self.model.index(0, column),
QtCore.Qt.DisplayRole,
text,
hits=-1,
flags=QtCore.Qt.MatchExactly,
)
item = QtGui.QStandardItem()
item.setData(len(indexes), QtCore.Qt.DisplayRole)
self.model2.setItem(0, i, item)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main = MainWidget()
main.show()
sys.exit(app.exec_())