Populating a ListView with Python Objects
-
I want to populate a ListView with objects from Python. I've been able to make a ListView work using ListModel+ ListElement in QML but not from Python. From what I've read, it seems I should use a QAbstractListModel but so far I haven't been able to get the values of the python objects to show up. It seems my QAbstractListModel's rowCount() and data() functions don't even get called.
I posted a (hopefully) lean example in a GitLab project
What am I missing?
Thanks,
-chris -
@Denni-0 Thanks for the tips Denni!
-
@christofer
Having glanced at your code. I can't help you if you sayrowCount()
ordata()
are never called. I know nothing about QML so only you know if your code is being called. It looks fine as-is except that yourdata()
method needs work.def data(self, index, role=Qt.DisplayRole): print("data: " + self.items) return self.items
First it must return the correct indvidual element according to the
index: QModelIndex
parameter, and second it must only do so for theDisplayRole
case on therole
parameter, not for all cases as you have done. Until you have done those 2 it won't work right.If/when that's sorted out, you're trying to have
data()
return aclass MyItem
data item, say for theDisplayRole
when it wants to show it. I can't imagine what a Qt view is going to make of that. If you're lucky it might usestr(instanceMyItem)
, and I don't know what that looks like. -
@Denni-0 just a side note, but the PySide2
QCoreApplication
,QGuiApplication
, andQApplication
haveexec_()
functions. The docs say things like "seeexec()
" but it doesn't exist. I get anAttributeError
if I try to use it. I'm using PySide2 version 5.14.1 -
@christofer You cannot expose a Python Object to QML, what you can do is export a QObject through the model as I have implemented in the PR to your repo.
-
@christofer You can also make the model expose each attribute of the items through the roles as I show in my second PR
-
@christofer said in Populating a ListView with Python Objects:
Still not sure the changes are correct because the functions do not get called
That sounds like a QML issue. You should heed what @eyllanesc has written, as he seems to know about Python to QML.
It really does not matter to try to change from
exec_()
toexec()
. PyQt exposes anexec()
(as well asexec_()
), PySide does not. As I said, nothing in your existing code I saw needed changing, it was not PyQt4 syntax, it was all correct, except for the implementation ofdata()
. -
Thanks @eyllanesc for the MRs! They're very helpful.
On using roles for
a
andb
(commit 1e5447) vs just using thedisplay
role (commit 83b42b) ... which do you recommend? I like the simple access in the QMLmodel.a
,model.b
but it seems like making custom roles could conflict with Qt expecting the roles in PySide2.QtCore.Qt.ItemDataRole which makes me thinkmodel.display.a
,model.display.b
is a safer long-term solution. -
Old post but Google led me here so it seemed like a place to drop a super-simple solution.
One approach that works very easily if you have a python list of QObject derived objects is to pass a QVariantList of QObjects and access them via @Property
class MyItemModel(QObject): ... @Property(str) def name(self): return self.m_name class MyDataModel(QObject): ... @Property('QVariantList') def names(self): return list(self.m_item_objects_list)
QML:
LiistView { id: lv model: mydatamodelinstance.names // setContextProperty of a MyDataModel object delegate: { Text { text: modelData.name } } // This gets the name property of a MyItemModel }