Change Data of subclassed QAbstractListModel in Python and show in QML ListView
-
Hello,
I try to implement a GUI with QML and Python. For that, I already implemented an own model (subclass of QAbstractListModel) to be displayed in a ListView. Now I want to change some data of the model, in fact, I want to call other functions and then display the result of this functions in my GUI. I already read something about signals and slots in Qt and I tried to implement a setData() method, cause I read that this is necessary for the data of the model to be changed. Now the problem is, that I don't know how to connect the method in the model with the properties of the QML file, e.g. I want to change the text field inside the ListView but I can't get it.
Here is some of my code.
The QML File:import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow { id: root visible: true width: 600 height: 650 title: "listview" ListView { id: listView width: 600 height: 510 //anchors.fill: parent model: _myModel delegate: Rectangle { id: bottleneck_rect height: childrenRect.height width: parent.width property alias label_rect: label_rect Rectangle { width: 290 height: 50 //color: "green" id: label_rect Text { id: label text: qsTr(model.label) font.family: "MS Shell Dlg 2" //font.family: "Inconsolata" font.pointSize: 14 anchors.verticalCenter: label_rect.verticalCenter; } anchors { left: parent.left; leftMargin: 10 } } } Rectangle { width: 600 height: 50 id: route_rect property alias mi_route_rect: measurement_info_route_rect Rectangle { width: 290 height: 50 id: label_route_rect Text { id: label_route text: qsTr("Route via") font.family: "Inconsolata" font.pointSize: 14 //color: "red" anchors.verticalCenter: label_route_rect.verticalCenter } anchors { left: parent.left; leftMargin: 10 } } Rectangle { property alias textroute: measurement_info_route width: 190 height: 50 id: measurement_info_route_rect Text { id: measurement_info_route text: "here" font.family: "Inconsolata" font.pointSize: 8 visible: true anchors.verticalCenter: measurement_info_route_rect.verticalCenter } anchors { left: label_route_rect.right; leftMargin: 15 } } anchors { bottom: listView.bottom; } } Button { id: details text: "Details" anchors { top: route_rect.bottom; topMargin: 40 } onClicked: { route_rect.mi_route_rect.textroute.visible = !route_rect.mi_route_rect.textroute.visible; } } } }
The Model mymodelqt.py:
#!/usr/bin/env python3 from enum import Enum from PyQt5.QtCore import QAbstractListModel, QMetaEnum, QTimer, QModelIndex, QVariant, QObject, QThread, pyqtSignal, pyqtSlot class Label: def __init__(self, label): super().__init__() self.label = label class MyModel(QAbstractListModel): def __init__(self): super().__init__() self._labels = [ Label("1rstlabel"), Label("2ndlabel"), Label("3rdlabel") ] class Roles(QMetaEnum): LabelRole = 1 def rowCount(self, parent): if parent.isValid(): return 0 return len(self._labels) def data(self, index, role): if not index: return QVariant if role == self.Roles.LabelRole: return self._labels[index.row()].label else: return QVariant def roleNames(self): _label = "label".encode('utf-8') mapping = { self.Roles.LabelRole: _label } return mapping def setData(self, index, value, role) -> bool: if not index.isValid(): return False if role == self.Roles.LabelRole: self._labels[index.row()].label = value return True textReturn = pyqtSignal(str, arguments=['txt']) @pyqtSlot(str) def details(self, text): print("Clicked the button") txt = text + " Jesus loves you" self.textReturn.emit(txt)
and the main Python-file:
import sys from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import QQmlApplicationEngine from mymodelqt import MyModel if __name__ =="__main__": app = QGuiApplication(sys.argv) myModel = MyModel() engine = QQmlApplicationEngine() engine.rootContext().setContextProperty("_myModel", myModel) engine.quit.connect(app.quit) engine.load('qt-forum.qml') sys.exit(app.exec_())
I want to change the name of label, e.g. from 1rstlabel to 0label, but in QML I can't get the property label of the Text from outside the ListView. I read something about properties and aliases and tried to implement it and it works for things outside the ListView, you can see that if you try to click the button. I got the visible-property of the text to show and hide the text. But as I said I can't reach the properties inside the ListView to be able to modify them.
I appreciate your help, thanks for reading this long post and thanks in advance for your advice!