QTableview Select 来自过滤模型的项目
QTableview Select Item from filtered model
我有一个使用 QStandardItemModel 的 QTableView。我如何 select table with/without 中的特定行应用搜索。
例如,我在搜索栏中键入 'y' 以过滤列表以仅显示包含字母 'y' 的行。当我单击按钮 'Select Emily' 时,考虑到用户可以更改排序顺序,我如何才能使其 select 成为 table 视图中的正确行?
import sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(400,400)
# controls
model = QtGui.QStandardItemModel(5, 3)
model.setHorizontalHeaderLabels(['NAME', 'AGE', 'CAREER'])
people = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Abby', 'age': 32, 'career': 'marketing'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Johnny', 'age': 27, 'career': 'soccer'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
for row, obj in enumerate(people):
item = QtGui.QStandardItem(obj['name'])
model.setItem(row, 0, item)
item = QtGui.QStandardItem(str(obj['age']))
model.setItem(row, 1, item)
item = QtGui.QStandardItem(obj['career'])
model.setItem(row, 2, item)
proxy_model = QtGui.QSortFilterProxyModel()
proxy_model.setSourceModel(model)
# controls
self.ui_table = QtGui.QTableView()
self.ui_table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.ui_table.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.ui_table.setModel(proxy_model)
self.ui_table.setSortingEnabled(False)
self.ui_table.setSortingEnabled(True)
self.ui_table.sortByColumn(0, self.ui_table.horizontalHeader().sortIndicatorOrder())
self.ui_search = QtGui.QLineEdit()
self.ui_selected = QtGui.QPushButton('Select Emily')
# lay main
lay_main = QtGui.QVBoxLayout()
lay_main.addWidget(self.ui_search)
lay_main.addWidget(self.ui_table)
lay_main.addWidget(self.ui_selected)
self.setLayout(lay_main)
# connections
self.ui_selected.clicked.connect(self.clicked_selected_emily)
self.ui_search.textChanged.connect(self.filter_items)
def clicked_selected_emily(self):
print 'select emily'
self.ui_table.selectRow(2)
def filter_items(self, text):
rows = self.ui_table.model().rowCount()
for row in range(rows):
self.filter_row(row, text)
def filter_row(self, row, pattern):
if not pattern:
self.ui_table.setRowHidden(row, False)
return
model = self.ui_table.model()
columns = model.columnCount()
stringlist = []
# collect text from all columns into single string for searching
for c in range(columns):
mdx = model.index(row, c)
if mdx.isValid():
val = str(mdx.data(role=QtCore.Qt.DisplayRole)).lower()
stringlist.append(val)
# search for string
patterns = filter(None, [x.lower() for x in pattern.split(' ')])
results = all(any(x in y for y in stringlist) for x in patterns)
if results:
self.ui_table.setRowHidden(row, False)
else:
self.ui_table.setRowHidden(row, True)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
你必须使用模型的match()方法:
def clicked_selected_emily(self):
print("select emily")
self.ui_table.clearSelection()
indexes = self.ui_table.model().match(
self.ui_table.model().index(0, 0),
QtCore.Qt.DisplayRole, # role of the search, the text uses the role Qt::DisplayRole
"Emily", # value that is being searched in the model.
-1, # maximum number of values are being searched, if it is -1 it will search for all the matches
QtCore.Qt.MatchExactly # type of search
)
for ix in indexes:
self.ui_table.selectRow(ix.row())
更新:
默认情况下,搜索是在前面的例子中传递给self.ui_table.model().index(0, col)
的列,如果你想搜索所有的列你应该只迭代它们,观察效果,多选是启用:
self.ui_table.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
...
def clicked_selected_emily(self):
print("select banker")
self.ui_table.clearSelection()
word = "banker"
for i in range(self.ui_table.model().columnCount()):
indexes = self.ui_table.model().match(
self.ui_table.model().index(0, i),
QtCore.Qt.DisplayRole, # role of the search, the text uses the role Qt::DisplayRole
"banker", # value that is being searched in the model.
-1, # maximum number of values are being searched, if it is -1 it will search for all the matches
QtCore.Qt.MatchExactly # type of search
)
for ix in indexes:
self.ui_table.selectRow(ix.row())
我有一个使用 QStandardItemModel 的 QTableView。我如何 select table with/without 中的特定行应用搜索。
例如,我在搜索栏中键入 'y' 以过滤列表以仅显示包含字母 'y' 的行。当我单击按钮 'Select Emily' 时,考虑到用户可以更改排序顺序,我如何才能使其 select 成为 table 视图中的正确行?
import sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(400,400)
# controls
model = QtGui.QStandardItemModel(5, 3)
model.setHorizontalHeaderLabels(['NAME', 'AGE', 'CAREER'])
people = [
{'name': 'Kevin', 'age': 5, 'career': 'athlete'},
{'name': 'Maggie', 'age': 13, 'career': 'banker'},
{'name': 'Leslie', 'age': 32, 'career': 'banker'},
{'name': 'Abby', 'age': 32, 'career': 'marketing'},
{'name': 'Emily', 'age': 45, 'career': 'athlete'},
{'name': 'David', 'age': 27, 'career': 'banker'},
{'name': 'Johnny', 'age': 27, 'career': 'soccer'},
{'name': 'Marie', 'age': 63, 'career': 'secretary'}
]
for row, obj in enumerate(people):
item = QtGui.QStandardItem(obj['name'])
model.setItem(row, 0, item)
item = QtGui.QStandardItem(str(obj['age']))
model.setItem(row, 1, item)
item = QtGui.QStandardItem(obj['career'])
model.setItem(row, 2, item)
proxy_model = QtGui.QSortFilterProxyModel()
proxy_model.setSourceModel(model)
# controls
self.ui_table = QtGui.QTableView()
self.ui_table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.ui_table.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.ui_table.setModel(proxy_model)
self.ui_table.setSortingEnabled(False)
self.ui_table.setSortingEnabled(True)
self.ui_table.sortByColumn(0, self.ui_table.horizontalHeader().sortIndicatorOrder())
self.ui_search = QtGui.QLineEdit()
self.ui_selected = QtGui.QPushButton('Select Emily')
# lay main
lay_main = QtGui.QVBoxLayout()
lay_main.addWidget(self.ui_search)
lay_main.addWidget(self.ui_table)
lay_main.addWidget(self.ui_selected)
self.setLayout(lay_main)
# connections
self.ui_selected.clicked.connect(self.clicked_selected_emily)
self.ui_search.textChanged.connect(self.filter_items)
def clicked_selected_emily(self):
print 'select emily'
self.ui_table.selectRow(2)
def filter_items(self, text):
rows = self.ui_table.model().rowCount()
for row in range(rows):
self.filter_row(row, text)
def filter_row(self, row, pattern):
if not pattern:
self.ui_table.setRowHidden(row, False)
return
model = self.ui_table.model()
columns = model.columnCount()
stringlist = []
# collect text from all columns into single string for searching
for c in range(columns):
mdx = model.index(row, c)
if mdx.isValid():
val = str(mdx.data(role=QtCore.Qt.DisplayRole)).lower()
stringlist.append(val)
# search for string
patterns = filter(None, [x.lower() for x in pattern.split(' ')])
results = all(any(x in y for y in stringlist) for x in patterns)
if results:
self.ui_table.setRowHidden(row, False)
else:
self.ui_table.setRowHidden(row, True)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
你必须使用模型的match()方法:
def clicked_selected_emily(self):
print("select emily")
self.ui_table.clearSelection()
indexes = self.ui_table.model().match(
self.ui_table.model().index(0, 0),
QtCore.Qt.DisplayRole, # role of the search, the text uses the role Qt::DisplayRole
"Emily", # value that is being searched in the model.
-1, # maximum number of values are being searched, if it is -1 it will search for all the matches
QtCore.Qt.MatchExactly # type of search
)
for ix in indexes:
self.ui_table.selectRow(ix.row())
更新:
默认情况下,搜索是在前面的例子中传递给self.ui_table.model().index(0, col)
的列,如果你想搜索所有的列你应该只迭代它们,观察效果,多选是启用:
self.ui_table.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
...
def clicked_selected_emily(self):
print("select banker")
self.ui_table.clearSelection()
word = "banker"
for i in range(self.ui_table.model().columnCount()):
indexes = self.ui_table.model().match(
self.ui_table.model().index(0, i),
QtCore.Qt.DisplayRole, # role of the search, the text uses the role Qt::DisplayRole
"banker", # value that is being searched in the model.
-1, # maximum number of values are being searched, if it is -1 it will search for all the matches
QtCore.Qt.MatchExactly # type of search
)
for ix in indexes:
self.ui_table.selectRow(ix.row())