J'aimerais savoir s'il est possible d'utiliser (plusieurs) délégués différents pour un QML ListView
.
En fonction de l'objet individuel dans le modèle ListView
, j'aimerais visualiser les objets avec différents délégués.
Ce morceau de code explique ce que je veux réaliser:
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
ListModel {
id: contactsModel
ListElement {
name: "Bill Smith"
position: "Engineer"
}
ListElement {
name: "John Brown"
position: "Engineer"
}
ListElement {
name: "Sam Wise"
position: "Manager"
}
}
ListView {
id: contactsView
anchors.left: parent.left
anchors.top: parent.top
width: parent.width
height: parent.height
orientation: Qt.Vertical
spacing: 10
model: contactsModel
delegate: {
if (position == "Engineer") return Employee; //<--- depending on condition, load Contact{}
else if (position == "Manager") return Manager; //<--- depending on condition, load Person{}
}
}
}
Employee.qml (Un composant possible que j'aimerais utiliser en tant que délégué)
import QtQuick 2.4
Rectangle{
width: 200
height: 50
color: ListView.isCurrentItem ? "#003366" : "#585858"
border.color: "gray"
border.width: 1
Text{
anchors.centerIn: parent
color: "white"
text: name
}
}
Manager.qml (autre composant que je voudrais utiliser en tant que délégué)
import QtQuick 2.4
Rectangle{
width: 200
height: 50
color: "red"
border.color: "blue"
border.width: 1
Text{
anchors.centerIn: parent
color: "white"
text: name
}
}
J'apprécierais n'importe quel conseil! Merci!
Je pense qu'il serait préférable d'implémenter un délégué de base pour tout type de position
qui charge une implémentation concrète en fonction de position
ou de toute autre propriété de données utilisant Loader
BaseDelegate {
property var position
Loader {
sourceComponent: {
switch(position) {
case "Engineer": return engineerDelegate
}
}
}
Component {
id: engineerDelegate
Rectangle {
Text { }
}
}
}
J'ai eu le même problème, la documentation Qt fournit une très bonne réponse: http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within- a-view-delegate
La solution la plus simple est une Component
en ligne avec une Loader
pour définir un fichier source
:
ListView {
id: contactsView
anchors.left: parent.left
anchors.top: parent.top
width: parent.width
height: parent.height
orientation: Qt.Vertical
spacing: 10
model: contactsModel
delegate: Component {
Loader {
source: switch(position) {
case "Engineer": return "Employee.qml"
case "Manager": return "Manager.qml"
}
}
}
}
Toute tentative d'utilisation de Loader.srcComponent
entraînera la perte de toute variable du modèle (y compris index
). La seule manière pour que les variables soient présentes est que les enfants Component
soient à l'intérieur de la Component
principale, mais un seul peut être présent, donc c'est inutile.
Je l'ai implémenté comme suit:
ListView {
id: iranCitiesList
model: sampleModel
delegate: Loader {
height: childrenRect.height
width: parent.width
sourceComponent: {
switch(itemType) {
case "image" :
return imageDel;
case "video":
return videoDel;
}
}
}
ImageDelegate { id: imageDel }
VideoDelegate { id: videoDel }
}
ImageDelegate.qml
Component {
Image { /*...*/ }
}
VideoDelegate.qml
Component {
Item { /*....*/ }
}
Dernière note, vérifiez la largeur et la hauteur des délégués. Dans mon cas, je devais régler la largeur et la hauteur de mon délégué dans Loader
.
Bonne chance - Mousavi
Dans la mesure où vous n’avez que deux types, le code suivant est aussi facile à gérer qu’à comprendre:
delegate: Item {
Employee { visible = position === "Engineer" }
Manager { visible = position === "Manager" }
}
Au cas où le nombre de types augmenterait, ce n'est pas une solution appropriée car cela mène facilement à une déclaration if si difficile.