This example illustrates how QSortFilterProxyModel and QAbstractListModel can be used to display a list of filterable items in QML and Python.
Run filtering.py
; it will load filtering.qml
which will need to be located in the same directory.
This example illustrates how QSortFilterProxyModel and QAbstractListModel can be used to display a list of filterable items in QML and Python.
Run filtering.py
; it will load filtering.qml
which will need to be located in the same directory.
import sys | |
from PyQt5 import QtCore, QtGui, QtQuick | |
class Model(QtCore.QAbstractListModel): | |
def __init__(self, parent=None): | |
super(Model, self).__init__(parent) | |
self.items = [ | |
{"name": "Item1"}, | |
{"name": "Item2"}, | |
{"name": "Item3"}, | |
{"name": "Item4"}, | |
{"name": "Item5"}, | |
{"name": "Item6"}, | |
{"name": "Item12"}, | |
{"name": "Item13"}, | |
{"name": "Item14"}, | |
] | |
self.roles = { | |
QtCore.Qt.UserRole + 1: "name" | |
} | |
def rowCount(self, parent=QtCore.QModelIndex()): | |
return len(self.items) | |
def data(self, index, role=QtCore.Qt.DisplayRole): | |
try: | |
item = self.items[index.row()] | |
except IndexError: | |
return QtCore.QVariant() | |
if role in self.roles: | |
return item.get(self.roles[role], QtCore.QVariant()) | |
return QtCore.QVariant() | |
def roleNames(self): | |
return self.roles | |
app = QtGui.QGuiApplication(sys.argv) | |
view = QtQuick.QQuickView() | |
model = Model() | |
proxy = QtCore.QSortFilterProxyModel() | |
proxy.setSourceModel(model) | |
proxy.setFilterRole(model.roles.keys()[0]) | |
proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) | |
engine = view.engine() | |
context = engine.rootContext() | |
context.setContextProperty("qmodel", proxy) | |
view.setSource(QtCore.QUrl("filtering.qml")) | |
view.setResizeMode(view.SizeRootObjectToView) | |
view.show() | |
app.exec_() |
import QtQuick 2.3 | |
import QtQuick.Controls 1.3 | |
Rectangle { | |
width: 400 | |
height: 500 | |
color: "brown" | |
TextField { | |
id: edit | |
placeholderText: "Filter.." | |
anchors.top: parent.top | |
anchors.left: parent.left | |
anchors.right: parent.right | |
anchors.margins: 10 | |
onTextChanged: qmodel.setFilterFixedString(text) | |
} | |
Rectangle { | |
color: "white" | |
radius: 2 | |
anchors.top: edit.bottom | |
anchors.left: parent.left | |
anchors.right: parent.right | |
anchors.bottom: parent.bottom | |
anchors.margins: 10 | |
ListView { | |
id: listView | |
clip: true | |
model: qmodel | |
spacing: 10 | |
anchors.fill: parent | |
anchors.margins: 5 | |
delegate: Text { | |
text: name | |
} | |
} | |
} | |
} |
Hi @sturmf, sorry for the delay, I'm didn't receive any notification!
To map the row number to the item, just use it as an index to that list.
model.items[row]
Very nice example. Thank you!
One small update: I had to set the object ownership for the proxy, or I would get a segfault:
engine.setObjectOwnership(proxy, QQmlApplicationEngine.JavaScriptOwnership)
Hi, how do you access the underlying item in case a row is activated? I get the row number in that case, but how do I map that back to the correct item?