web-dev-qa-db-ja.com

QMLリストビューのさまざまなデリゲート

QML ListViewに(いくつかの)異なるデリゲートを使用できるかどうか知りたいのですが。

ListViewモデルの個々のオブジェクトに応じて、さまざまなデリゲートでオブジェクトを視覚化したいと思います。

このコードは、私が達成したいことを説明しています。

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(デリゲートとして使用したいコンポーネントの1つ)

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(デリゲートとして使用したい他のコンポーネント)

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
    }
}

私はアドバイスをいただければ幸いです!ありがとう!

22
dh1tw

私は同じ問題を抱えていましたが、Qtドキュメントはかなり良い答えを提供しています: http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader- within-a-view-delegate

最も簡単な解決策は、Componentファイルを設定するLoaderを含むインライン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"
            }
        }
    }
}

Loader.srcComponentを使用しようとすると、モデルから変数が失われます(indexを含む)。変数が存在する唯一の方法は、子ComponentがメインComponent内にあることですが、存在できるのは1つだけなので、それは役に立ちません。

16

positionまたはpositionを使用する他のデータプロパティに応じて具体的な実装をロードするすべての種類のLoaderに1つの基本デリゲートを実装する方が良いと思います

BaseDelegate {
    property var position

    Loader {
        sourceComponent: {
            switch(position) {
                case "Engineer": return engineerDelegate
            }
        }
    }

    Component {
        id: engineerDelegate
        Rectangle {
             Text {  }
        }
    }
}
11
Andrii

私はそれを次のように実装しました:

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 { /*....*/ }
}

最後に、デリゲートの幅と高さを確認してください。私の場合、デリゲートの幅と高さをLoaderに再度設定する必要がありました。
頑張ってください-Mousavi

8
S.M.Mousavi

タイプが2つしかない限り、次のコードは保守が簡単で理解も簡単です。

delegate: Item {
    Employee { visible = position === "Engineer" }
    Manager { visible = position === "Manager" }
}

タイプの数が増える場合は、ifステートメントの地獄に簡単につながるため、適切なソリューションではありません。

0
skypjack