如何在列标题中实现QLineEdit来过滤QTreeView中的数据?
预期结果如下:
到目前为止,我已经知道了:
到目前为止,除了过滤器的QLineEdit以外,我什么都没有。 完整的工作代码示例(必须使用peewee ORM):
import sys
import re
from peewee import *
from PyQt5 import QtWidgets, QtGui, QtCore
COUNT_PERS_COLS = 3
col_persID, col_persLAST_NAME, col_persFIRST_NAME = range(COUNT_PERS_COLS)
db = SqliteDatabase(':memory:')
def _human_key(key):
parts = re.split(r'(\d*\.\d+|\d+)', key)
return tuple((e.swapcase() if i % 2 == 0 else float(e))
for i, e in enumerate(parts))
class FilterHeader(QtWidgets.QHeaderView):
filterActivated = QtCore.pyqtSignal()
def __init__(self, parent):
super().__init__(QtCore.Qt.Horizontal, parent)
self._editors = []
self._padding = 4
self.setStretchLastSection(True)
# self.setResizeMode(QHeaderView.Stretch) obsolete
self.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
self.setDefaultAlignment(
QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.setSortIndicatorShown(False)
self.sectionResized.connect(self.adjustPositions)
parent.horizontalScrollBar().valueChanged.connect(
self.adjustPositions)
def setFilterBoxes(self, count):
while self._editors:
editor = self._editors.pop()
editor.deleteLater()
for index in range(count):
editor = QtWidgets.QLineEdit(self.parent())
editor.setPlaceholderText('Filter')
editor.returnPressed.connect(self.filterActivated.emit)
self._editors.append(editor)
self.adjustPositions()
def sizeHint(self):
size = super().sizeHint()
if self._editors:
height = self._editors[0].sizeHint().height()
size.setHeight(size.height() + height + self._padding)
return size
def updateGeometries(self):
if self._editors:
height = self._editors[0].sizeHint().height()
self.setViewportMargins(0, 0, 0, height + self._padding)
else:
self.setViewportMargins(0, 0, 0, 0)
super().updateGeometries()
self.adjustPositions()
def adjustPositions(self):
for index, editor in enumerate(self._editors):
height = editor.sizeHint().height()
editor.move(
self.sectionPosition(index) - self.offset() + 2,
height + (self._padding // 2))
editor.resize(self.sectionSize(index), height)
def filterText(self, index):
if 0 <= index < len(self._editors):
return self._editors[index].text()
return ''
def setFilterText(self, index, text):
if 0 <= index < len(self._editors):
self._editors[index].setText(text)
def clearFilters(self):
for editor in self._editors:
editor.clear()
class HumanProxyModel(QtCore.QSortFilterProxyModel):
def lessThan(self, source_left, source_right):
data_left = source_left.data()
data_right = source_right.data()
if type(data_left) == type(data_right) == str:
return _human_key(data_left) < _human_key(data_right)
return super(HumanProxyModel, self).lessThan(source_left, source_right)
class Person(Model):
persId = CharField()
lastName = CharField()
firstName = CharField()
class Meta:
database = db
class winMain(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
self.setGeometry(300,200,700,500)
self.show()
def createPersonModel(self,parent):
model = QtGui.QStandardItemModel(0, COUNT_PERS_COLS, parent)
#model.setHeaderData(col_persID, QtCore.Qt.Horizontal, "ID")
#model.setHeaderData(col_persLAST_NAME, QtCore.Qt.Horizontal, "Last Name")
#model.setHeaderData(col_persFIRST_NAME, QtCore.Qt.Horizontal, "First Name")
#model.setHorizontalHeaderLabels('One Two Three' .split())
model.setHorizontalHeaderLabels(['ID', 'Last Name', 'First Name'])
return model
def addPerson(self, model, id, last_name, first_name):
model.insertRow(0)
model.setData(model.index(0, col_persID), id)
model.setData(model.index(0, col_persLAST_NAME), last_name)
model.setData(model.index(0, col_persFIRST_NAME), first_name)
def handleFilterActivated(self):
#header = self.tableView.horizontalHeader() # QTableView()-command
header = self.treeView.header()
for index in range(header.count()):
print((index, header.filterText(index)))
def setupUi(self):
self.treeView = QtWidgets.QTreeView(self)
self.treeView.setGeometry(0,0,700,500)
self.treeView.setSortingEnabled(True)
self.treeView.setAlternatingRowColors(True)
self.treeView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.treeView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.treeView.setAnimated(True)
self.treeView.setItemsExpandable(True)
#layout = QtWidgets.QVBoxLayout(self)
#layout.addWidget(self.treeView)
header = FilterHeader(self.treeView)
# self.tableView.setHorizontalHeader(header) # QTableView()-command
self.treeView.setHeader(header)
model = self.createPersonModel(self)
self.treeView.setModel(model)
proxy = HumanProxyModel(self)
proxy.setSourceModel(model)
self.treeView.setModel(proxy)
header.setFilterBoxes(model.columnCount())
header.filterActivated.connect(self.handleFilterActivated)
for rec_person in Person.select():
self.addPerson(model, rec_person.persId, rec_person.lastName, rec_person.firstName)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
# create a table for our model
db.create_tables([Person])
# create some sample data for our model
Person.create(persId='1001', lastName='Martin', firstName='Robert')
Person.create(persId='1002', lastName='Smith', firstName='Brad')
Person.create(persId='1003', lastName='Smith', firstName='Angelina')
window = winMain()
sys.exit(app.exec_())
我已经使用QSortFilterProxyModel类通过单击列标题来对结果进行排序。
答案 0 :(得分:2)
您必须通过实现过滤逻辑来覆盖filterAcceptsRow方法,在以下示例中,将使用以下规则对其进行过滤:
route /P add 172.18.0.0 MASK 255.255.0.0 10.0.75.2