在 QTableView 中使用 QSortFilterProxyModel 对两行进行排序
Sorting two rows using QSortFilterProxyModel in QTableView
我在尝试让我的过滤器为我的 QTableView 工作时遇到问题;目前它只适用于第一列,但我正在尝试使用 QLineEdit 过滤前两列。它应该匹配第一列或第二列。
我正在努力制作一个最小的示例,但只是看看是否有人可以看出我是否只是在我的代码中犯了一些简单的错误。
将 for 循环中的 'i' 更改为单个列(0 或 1)有效,但没有按预期工作,因为它只是过滤特定的列。
class SortFilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QtCore.QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.filters = {}
def setFilterByColumn(self, regex, column):
self.filters[column] = regex
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
for key, regex in self.filters.items():
ix = self.sourceModel().index(source_row, key, source_parent)
if ix.isValid():
text = self.sourceModel().data(ix)
if regex.indexIn(text) == -1:
return False
return True
class Database(QtWidgets.QMainWindow, Ui_databaseWindow):
def __init__(self,parent=None):
super().__init__()
self.setupUi(self)
self.mainTableView.clicked.connect(self.tableInfo)
self.radioGroup = QtWidgets.QButtonGroup()
self.radioGroup.addButton(self.frameView) # below are radio buttons
self.radioGroup.addButton(self.cylView)
self.radioGroup.addButton(self.driversView)
self.radioGroup.addButton(self.valView)
self.radioGroup.addButton(self.fixedView)
self.radioGroup.addButton(self.vvcpView)
self.frameView.setChecked(True)
self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("C:\Workspace\Database\data.db")
self.db.open()
self.projectModel = QtSql.QSqlQueryModel()
self.proxyModel = SortFilterProxyModel(self)
self.proxyModel.setSourceModel(self.projectModel)
self.radioGroup.buttonClicked.connect(self.checkState)
self.projectModel.setQuery("select * from tblBasic_Frame",self.db)
self.mainTableView.setModel(self.proxyModel)
self.mainTableView.setSortingEnabled(True)
self.sortBox.textChanged.connect(self.onTextChanged) #QLineEdit
@QtCore.pyqtSlot(str)
def onTextChanged(self, text):
if self.valveView.isChecked():
for i in range(0,2):
self.proxyModel.setFilterByColumn(QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive),i)
else:
self.proxyModel.setFilterByColumn(QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive),0)
您的代码存在以下错误:
如果第一列中的文本与文本不匹配那么你 return False 表示不显示该行而不考虑可能与第二列匹配。
假设您已经过滤了 2 列并更改了 valveView 的状态,这只会更新第一列的正则表达式,因此它仍会使用之前的正则表达式过滤第二列。
如果 QLineEdit 中没有文本,那么您必须清理过滤器。
当 valveView 状态改变时,您还必须更新过滤器状态。
class SortFilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QtCore.QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.filters = {}
def setFilterByColumn(self, regex, column):
self.filters[column] = regex
self.invalidateFilter()
def clear_filter(self):
self.filters = {}
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
values = []
if self.filters:
for key, regex in self.filters.items():
text = self.sourceModel().index(source_row, key, source_parent).data()
values.append(regex.indexIn(text) != -1)
return any(values)
return True
class Database(QtWidgets.QMainWindow, Ui_databaseWindow):
def __init__(self,parent=None):
super().__init__()
self.setupUi(self)
self.mainTableView.clicked.connect(self.tableInfo)
self.radioGroup = QtWidgets.QButtonGroup()
self.radioGroup.addButton(self.frameView) # below are radio buttons
self.radioGroup.addButton(self.cylView)
self.radioGroup.addButton(self.driversView)
self.radioGroup.addButton(self.valView)
self.radioGroup.addButton(self.fixedView)
self.radioGroup.addButton(self.vvcpView)
self.frameView.setChecked(True)
self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("C:\Workspace\Database\data.db")
self.db.open()
self.projectModel = QtSql.QSqlQueryModel()
self.proxyModel = SortFilterProxyModel(self)
self.proxyModel.setSourceModel(self.projectModel)
self.radioGroup.buttonClicked.connect(self.checkState)
self.projectModel.setQuery("select * from tblBasic_Frame",self.db)
self.mainTableView.setModel(self.proxyModel)
self.mainTableView.setSortingEnabled(True)
self.sortBox.textChanged.connect(self.update_filter) #QLineEdit
self.valveView.toggled.connect(self.update_filter)
@QtCore.pyqtSlot()
def update_filter(self):
text = self.sortBox.text()
self.proxyModel.clear_filter()
if text:
if self.valveView.isChecked():
for i in range(2):
self.proxyModel.setFilterByColumn(
QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive), i
)
else:
self.proxyModel.setFilterByColumn(
QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive), 0
)
我在尝试让我的过滤器为我的 QTableView 工作时遇到问题;目前它只适用于第一列,但我正在尝试使用 QLineEdit 过滤前两列。它应该匹配第一列或第二列。
我正在努力制作一个最小的示例,但只是看看是否有人可以看出我是否只是在我的代码中犯了一些简单的错误。
将 for 循环中的 'i' 更改为单个列(0 或 1)有效,但没有按预期工作,因为它只是过滤特定的列。
class SortFilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QtCore.QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.filters = {}
def setFilterByColumn(self, regex, column):
self.filters[column] = regex
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
for key, regex in self.filters.items():
ix = self.sourceModel().index(source_row, key, source_parent)
if ix.isValid():
text = self.sourceModel().data(ix)
if regex.indexIn(text) == -1:
return False
return True
class Database(QtWidgets.QMainWindow, Ui_databaseWindow):
def __init__(self,parent=None):
super().__init__()
self.setupUi(self)
self.mainTableView.clicked.connect(self.tableInfo)
self.radioGroup = QtWidgets.QButtonGroup()
self.radioGroup.addButton(self.frameView) # below are radio buttons
self.radioGroup.addButton(self.cylView)
self.radioGroup.addButton(self.driversView)
self.radioGroup.addButton(self.valView)
self.radioGroup.addButton(self.fixedView)
self.radioGroup.addButton(self.vvcpView)
self.frameView.setChecked(True)
self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("C:\Workspace\Database\data.db")
self.db.open()
self.projectModel = QtSql.QSqlQueryModel()
self.proxyModel = SortFilterProxyModel(self)
self.proxyModel.setSourceModel(self.projectModel)
self.radioGroup.buttonClicked.connect(self.checkState)
self.projectModel.setQuery("select * from tblBasic_Frame",self.db)
self.mainTableView.setModel(self.proxyModel)
self.mainTableView.setSortingEnabled(True)
self.sortBox.textChanged.connect(self.onTextChanged) #QLineEdit
@QtCore.pyqtSlot(str)
def onTextChanged(self, text):
if self.valveView.isChecked():
for i in range(0,2):
self.proxyModel.setFilterByColumn(QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive),i)
else:
self.proxyModel.setFilterByColumn(QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive),0)
您的代码存在以下错误:
如果第一列中的文本与文本不匹配那么你 return False 表示不显示该行而不考虑可能与第二列匹配。
假设您已经过滤了 2 列并更改了 valveView 的状态,这只会更新第一列的正则表达式,因此它仍会使用之前的正则表达式过滤第二列。
如果 QLineEdit 中没有文本,那么您必须清理过滤器。
当 valveView 状态改变时,您还必须更新过滤器状态。
class SortFilterProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QtCore.QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.filters = {}
def setFilterByColumn(self, regex, column):
self.filters[column] = regex
self.invalidateFilter()
def clear_filter(self):
self.filters = {}
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
values = []
if self.filters:
for key, regex in self.filters.items():
text = self.sourceModel().index(source_row, key, source_parent).data()
values.append(regex.indexIn(text) != -1)
return any(values)
return True
class Database(QtWidgets.QMainWindow, Ui_databaseWindow):
def __init__(self,parent=None):
super().__init__()
self.setupUi(self)
self.mainTableView.clicked.connect(self.tableInfo)
self.radioGroup = QtWidgets.QButtonGroup()
self.radioGroup.addButton(self.frameView) # below are radio buttons
self.radioGroup.addButton(self.cylView)
self.radioGroup.addButton(self.driversView)
self.radioGroup.addButton(self.valView)
self.radioGroup.addButton(self.fixedView)
self.radioGroup.addButton(self.vvcpView)
self.frameView.setChecked(True)
self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("C:\Workspace\Database\data.db")
self.db.open()
self.projectModel = QtSql.QSqlQueryModel()
self.proxyModel = SortFilterProxyModel(self)
self.proxyModel.setSourceModel(self.projectModel)
self.radioGroup.buttonClicked.connect(self.checkState)
self.projectModel.setQuery("select * from tblBasic_Frame",self.db)
self.mainTableView.setModel(self.proxyModel)
self.mainTableView.setSortingEnabled(True)
self.sortBox.textChanged.connect(self.update_filter) #QLineEdit
self.valveView.toggled.connect(self.update_filter)
@QtCore.pyqtSlot()
def update_filter(self):
text = self.sortBox.text()
self.proxyModel.clear_filter()
if text:
if self.valveView.isChecked():
for i in range(2):
self.proxyModel.setFilterByColumn(
QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive), i
)
else:
self.proxyModel.setFilterByColumn(
QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive), 0
)