使用 PySide 搜索 QTableView 中的所有行
Search all rows in QTableView using PySide
如何使用搜索字符串过滤 QTableView 中的行,该搜索字符串检查每行每列的每个显示角色的值?请记住,在这种情况下,可见的列可以根据复选框进行更改。同时保持通过单击列 headers.
对行进行排序的能力
import os, sys, json, pprint
sys.path.append(os.environ.get('PS_SITEPACKAGES'))
from Qt import QtGui, QtWidgets, QtCore
class QDictTableView(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(QDictTableView, self).__init__(*args, **kwargs)
self.resize(400,300)
# controls
self.ui_search_input = QtWidgets.QLineEdit()
self.ui_search_input.setPlaceholderText('Search...')
self.ui_name_filter = QtWidgets.QCheckBox('Name')
self.ui_age_filter = QtWidgets.QCheckBox('Age')
self.ui_career_filter = QtWidgets.QCheckBox('Career')
self.ui_item_table = QtWidgets.QTableView()
self.ui_item_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.ui_item_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.ui_item_table.verticalHeader().hide()
self.ui_item_table.setModel(QtGui.QStandardItemModel())
# lay main
lay_filters = QtWidgets.QHBoxLayout()
lay_filters.addWidget(self.ui_name_filter)
lay_filters.addWidget(self.ui_age_filter)
lay_filters.addWidget(self.ui_career_filter)
lay_main = QtWidgets.QVBoxLayout()
lay_main.setAlignment(QtCore.Qt.AlignTop)
lay_main.addWidget(self.ui_search_input)
lay_main.addLayout(lay_filters)
lay_main.addWidget(self.ui_item_table)
self.setLayout(lay_main)
# connections
self.ui_search_input.textChanged.connect(self.changed_text)
self.ui_name_filter.stateChanged.connect(self.populate_table)
self.ui_age_filter.stateChanged.connect(self.populate_table)
self.ui_career_filter.stateChanged.connect(self.populate_table)
# being
self.populate_table()
self.ui_name_filter.setChecked(True)
self.ui_age_filter.setChecked(True)
self.ui_career_filter.setChecked(True)
# methods
def changed_text(self, text):
print 'SEARCHING:', text
def populate_table(self):
people = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
model = self.ui_item_table.model()
model.clear()
self.ui_item_table.setSortingEnabled(False)
# column headers
headers = []
if self.ui_name_filter.isChecked():
headers.append('Name')
if self.ui_age_filter.isChecked():
headers.append('Age')
if self.ui_career_filter.isChecked():
headers.append('Career')
model.setHorizontalHeaderLabels(headers)
# model.setHeaderData( i, Qt::Horizontal,thermoNames.at(i));
# populate rows
for x in people:
row = []
if self.ui_name_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('name', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
if self.ui_age_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('age', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
headers.append('Age')
if self.ui_career_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('career', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
headers.append('Career')
model.appendRow(row)
# update ui after
self.ui_item_table.setSortingEnabled(True)
self.ui_item_table.sortByColumn(0, QtCore.Qt.AscendingOrder)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = QDictTableView()
ex.show()
sys.exit(app.exec_())
如果你想过滤数据你必须使用QSortFilterProxyModel
并覆盖filterAcceptsRow()
方法,另一方面,每次创建模型并不优雅,你只能隐藏列setColumnHidden()
QTableView
的方法。
import sys
import os
sys.path.append(os.environ.get('PS_SITEPACKAGES'))
from Qt import QtGui, QtWidgets, QtCore
from functools import partial
class FilterProxy(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(FilterProxy, self).__init__(*args, **kwargs)
self.filters_colums = set()
self.mText = ""
def setText(self, text):
self.mText = text
self.invalidateFilter()
def appendColumn(self, name):
self.filters_colums.add(name.lower())
self.invalidateFilter()
def removeColumn(self, name):
self.filters_colums.discard(name.lower())
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
if self.mText:
for i in range(self.sourceModel().columnCount()):
header = self.sourceModel().headerData(i, QtCore.Qt.Horizontal)
text = self.sourceModel().index(source_row, i).data()
if header in self.filters_colums and self.mText in text.lower():
return True
return False
return True
class QDictTableView(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(QDictTableView, self).__init__(*args, **kwargs)
self.resize(400,300)
# controls
self.ui_search_input = QtWidgets.QLineEdit()
self.ui_search_input.setPlaceholderText('Search...')
self.ui_item_table = QtWidgets.QTableView()
self.ui_item_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.ui_item_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.ui_item_table.verticalHeader().hide()
lay_filters = QtWidgets.QHBoxLayout()
lay_main = QtWidgets.QVBoxLayout(self)
lay_main.setAlignment(QtCore.Qt.AlignTop)
lay_main.addWidget(self.ui_search_input)
lay_main.addLayout(lay_filters)
lay_main.addWidget(self.ui_item_table)
model = self.populate_table()
self.proxy = FilterProxy()
self.proxy.setSourceModel(model)
self.ui_item_table.setModel(self.proxy)
for text in ("Name", "Age", "Career"):
checkbox = QtWidgets.QCheckBox(text)
checkbox.stateChanged.connect(partial(self.update_columns, text))
checkbox.setChecked(True)
lay_filters.addWidget(checkbox)
self.ui_search_input.textChanged.connect(self.proxy.setText)
def update_columns(self, text, state):
cols = self.ui_item_table.model().columnCount()
i = [self.ui_item_table.model().headerData(i, QtCore.Qt.Horizontal) for i in range(cols)].index(text.lower())
self.ui_item_table.setColumnHidden(i, state == QtCore.Qt.Unchecked)
if state == QtCore.Qt.Unchecked:
self.proxy.removeColumn(text)
else:
self.proxy.appendColumn(text)
def populate_table(self):
peoples = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
model = QtGui.QStandardItemModel()
headers = ["name", "age", "career"]
model.setHorizontalHeaderLabels(headers)
for row, people in enumerate(peoples):
items = []
for key, value in people.items():
col = headers.index(key)
item = QtGui.QStandardItem(str(value))
items.append(item)
model.insertRow(row, items)
return model
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = QDictTableView()
ex.show()
sys.exit(app.exec_())
如何使用搜索字符串过滤 QTableView 中的行,该搜索字符串检查每行每列的每个显示角色的值?请记住,在这种情况下,可见的列可以根据复选框进行更改。同时保持通过单击列 headers.
对行进行排序的能力import os, sys, json, pprint
sys.path.append(os.environ.get('PS_SITEPACKAGES'))
from Qt import QtGui, QtWidgets, QtCore
class QDictTableView(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(QDictTableView, self).__init__(*args, **kwargs)
self.resize(400,300)
# controls
self.ui_search_input = QtWidgets.QLineEdit()
self.ui_search_input.setPlaceholderText('Search...')
self.ui_name_filter = QtWidgets.QCheckBox('Name')
self.ui_age_filter = QtWidgets.QCheckBox('Age')
self.ui_career_filter = QtWidgets.QCheckBox('Career')
self.ui_item_table = QtWidgets.QTableView()
self.ui_item_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.ui_item_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.ui_item_table.verticalHeader().hide()
self.ui_item_table.setModel(QtGui.QStandardItemModel())
# lay main
lay_filters = QtWidgets.QHBoxLayout()
lay_filters.addWidget(self.ui_name_filter)
lay_filters.addWidget(self.ui_age_filter)
lay_filters.addWidget(self.ui_career_filter)
lay_main = QtWidgets.QVBoxLayout()
lay_main.setAlignment(QtCore.Qt.AlignTop)
lay_main.addWidget(self.ui_search_input)
lay_main.addLayout(lay_filters)
lay_main.addWidget(self.ui_item_table)
self.setLayout(lay_main)
# connections
self.ui_search_input.textChanged.connect(self.changed_text)
self.ui_name_filter.stateChanged.connect(self.populate_table)
self.ui_age_filter.stateChanged.connect(self.populate_table)
self.ui_career_filter.stateChanged.connect(self.populate_table)
# being
self.populate_table()
self.ui_name_filter.setChecked(True)
self.ui_age_filter.setChecked(True)
self.ui_career_filter.setChecked(True)
# methods
def changed_text(self, text):
print 'SEARCHING:', text
def populate_table(self):
people = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
model = self.ui_item_table.model()
model.clear()
self.ui_item_table.setSortingEnabled(False)
# column headers
headers = []
if self.ui_name_filter.isChecked():
headers.append('Name')
if self.ui_age_filter.isChecked():
headers.append('Age')
if self.ui_career_filter.isChecked():
headers.append('Career')
model.setHorizontalHeaderLabels(headers)
# model.setHeaderData( i, Qt::Horizontal,thermoNames.at(i));
# populate rows
for x in people:
row = []
if self.ui_name_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('name', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
if self.ui_age_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('age', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
headers.append('Age')
if self.ui_career_filter.isChecked():
col = QtGui.QStandardItem()
col.setData(x.get('career', 'NA'), role=QtCore.Qt.DisplayRole)
col.setData(x, role=QtCore.Qt.UserRole)
row.append(col)
headers.append('Career')
model.appendRow(row)
# update ui after
self.ui_item_table.setSortingEnabled(True)
self.ui_item_table.sortByColumn(0, QtCore.Qt.AscendingOrder)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = QDictTableView()
ex.show()
sys.exit(app.exec_())
如果你想过滤数据你必须使用QSortFilterProxyModel
并覆盖filterAcceptsRow()
方法,另一方面,每次创建模型并不优雅,你只能隐藏列setColumnHidden()
QTableView
的方法。
import sys
import os
sys.path.append(os.environ.get('PS_SITEPACKAGES'))
from Qt import QtGui, QtWidgets, QtCore
from functools import partial
class FilterProxy(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(FilterProxy, self).__init__(*args, **kwargs)
self.filters_colums = set()
self.mText = ""
def setText(self, text):
self.mText = text
self.invalidateFilter()
def appendColumn(self, name):
self.filters_colums.add(name.lower())
self.invalidateFilter()
def removeColumn(self, name):
self.filters_colums.discard(name.lower())
self.invalidateFilter()
def filterAcceptsRow(self, source_row, source_parent):
if self.mText:
for i in range(self.sourceModel().columnCount()):
header = self.sourceModel().headerData(i, QtCore.Qt.Horizontal)
text = self.sourceModel().index(source_row, i).data()
if header in self.filters_colums and self.mText in text.lower():
return True
return False
return True
class QDictTableView(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(QDictTableView, self).__init__(*args, **kwargs)
self.resize(400,300)
# controls
self.ui_search_input = QtWidgets.QLineEdit()
self.ui_search_input.setPlaceholderText('Search...')
self.ui_item_table = QtWidgets.QTableView()
self.ui_item_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.ui_item_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.ui_item_table.verticalHeader().hide()
lay_filters = QtWidgets.QHBoxLayout()
lay_main = QtWidgets.QVBoxLayout(self)
lay_main.setAlignment(QtCore.Qt.AlignTop)
lay_main.addWidget(self.ui_search_input)
lay_main.addLayout(lay_filters)
lay_main.addWidget(self.ui_item_table)
model = self.populate_table()
self.proxy = FilterProxy()
self.proxy.setSourceModel(model)
self.ui_item_table.setModel(self.proxy)
for text in ("Name", "Age", "Career"):
checkbox = QtWidgets.QCheckBox(text)
checkbox.stateChanged.connect(partial(self.update_columns, text))
checkbox.setChecked(True)
lay_filters.addWidget(checkbox)
self.ui_search_input.textChanged.connect(self.proxy.setText)
def update_columns(self, text, state):
cols = self.ui_item_table.model().columnCount()
i = [self.ui_item_table.model().headerData(i, QtCore.Qt.Horizontal) for i in range(cols)].index(text.lower())
self.ui_item_table.setColumnHidden(i, state == QtCore.Qt.Unchecked)
if state == QtCore.Qt.Unchecked:
self.proxy.removeColumn(text)
else:
self.proxy.appendColumn(text)
def populate_table(self):
peoples = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
model = QtGui.QStandardItemModel()
headers = ["name", "age", "career"]
model.setHorizontalHeaderLabels(headers)
for row, people in enumerate(peoples):
items = []
for key, value in people.items():
col = headers.index(key)
item = QtGui.QStandardItem(str(value))
items.append(item)
model.insertRow(row, items)
return model
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = QDictTableView()
ex.show()
sys.exit(app.exec_())