I have a list in QML and displaying it in a listView object. I need to access this data from python when a button is pressed. In Python I create a QStringListModel object and bind it to my listModel in QML using setContextProperty. I can see the list being created and displayed as expected in QML, however when I want to access the data from python, the list is empty. Here is the code:
QML:
import QtQuick 2.0
import QtQuick.Controls 2.3
Rectangle{
id: root
width:800
height:600
ListView {
id: listView
x: 476
y: 64
width: 110
height: 160
model: myModel
ListModel {
id: myModel
ListElement {
name: "Grey"
colorCode: "grey"
}
ListElement {
name: "Red"
colorCode: "red"
}
ListElement {
name: "Blue"
colorCode: "blue"
}
ListElement {
name: "Green"
colorCode: "green"
}
}
delegate: Item {
x: 5
width: 80
height: 40
Row {
id: row1
Rectangle {
width: 40
height: 40
color: colorCode
}
Text {
text: name
anchors.verticalCenter: parent.verticalCenter
font.bold: true
}
spacing: 10
}
}
}
}
Python:
import sys
from PyQt5.QtCore import QUrl, QStringListModel
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
app = QApplication(sys.argv)
view = QQuickView()
view.setSource(QUrl("main.qml"))
pyList = QStringListModel()
view.rootContext().setContextProperty("myModel",pyList)
print(pyList.stringList())
print(pyList.rowCount())
view.show()
print("Done!")
sys.exit(app.exec_())
I was on the impression that when we use python bindings, the object created in python is bound to the QML object. Therefore if the QML list has data (dynamically created in the UI), the python list should automatically be filled with that data? What am I missing?
You are assuming that because you pass a model through setContextProperty() that has the same name as the ListModel are the same, no, and on the contrary it causes your program to be unstable since QML overlaps both names. Instead you have to create a model in python and export it, but since you also want to interact with the QML it is better to export a QObject that has the model as qproperty. Do not use findChild, findChildren to get QML elements in python, you must do the opposite of exporting elements from python to QML.
Considering the above, I have implemented a Manager class that has the qproperty model, in addition to a slot that can be invoked from QML. To avoid complicating the code, I used the QStandardItemModel class as the basis of the model, QStringListModel is a read-only model, so it does not work for this case.
main.py
main.qml
I recommend you read my another answer for a more detailed explanation.