QML DelegateModel: доступ к DelegateModel из делегата. - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь создать ListView с различными делегатами и функциональностью drag'n'drop.Делегаты должны быть загружены с загрузчиком.

Документация QML предоставляет рабочий пример для ListView без загрузчика: http://doc.qt.io/qt-5/qtquick-tutorials-dynamicview-dynamicview3-example.html

Однако, используя загрузчик, я получаю сообщение об ошибке: Не удается прочитатьсвойство DelegateModel неопределенного

Я не понимаю, как получить доступ к DelegateModel из загрузчика.

Подсказка для решения очень важна!

main.qml:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.1
import QtQml.Models 2.3

Window {
    id: mainroot

    visible: true
    width: 640
    height: 480

    Rectangle{
        id:viewContainer

        anchors.fill: parent

        DelegateModel {
            id: visualModel

            model: ListModel{
                id:m_model

                ListElement{
                    type:1
                    m_text :"Text1"
                }

                ListElement{
                    type:1
                    m_text :"Text2"
                }
            }

            delegate:        Loader{
                id:idLoader

                width: view.width
                height: childrenRect.height

                Component.onCompleted: {
                    switch(type){
                    case 1:
                        idLoader.setSource("TestDelegate.qml", {"m_text": m_text})
                        break;
                    }
                }
            }
        }

        ListView{
            id: view

            anchors.fill: parent
            spacing: 5

            model: visualModel
        }
    }
}

TestDelegate.qml:

    import QtQuick 2.7

MouseArea {
    id: dragArea

    property bool held: false
    property string m_text

    anchors { left: parent.left; right: parent.right }
    height: 50
    width: view.width

    drag.target: held ? content : undefined
    drag.axis: Drag.YAxis

    onPressAndHold: held = true
    onReleased: held = false

    Rectangle {
        id: content

        anchors {
            horizontalCenter: parent.horizontalCenter
            verticalCenter: parent.verticalCenter
        }
        width: dragArea.width
        height: textfield.implicitHeight


        Drag.active: dragArea.held
        Drag.source: dragArea
        Drag.hotSpot.x: width / 2
        Drag.hotSpot.y: height / 2

        border.width: 1
        border.color: "lightsteelblue"
        color: dragArea.held ? "lightsteelblue" : "white"
        Behavior on color { ColorAnimation { duration: 100 } }
        radius: 2
        states: State {
            when: dragArea.held

            ParentChange { target: content; parent: viewContainer }
            AnchorChanges {
                target: content
                anchors { horizontalCenter: undefined; verticalCenter: undefined }
            }
        }

        Text{
            id: textfield

            anchors.centerIn: parent
            text: m_text
        }

    }
    DropArea {
        anchors { fill: parent; margins: 10 }

        onEntered: {
            visualModel.items.move(
                    idLoader.item.drag.source.DelegateModel.itemsIndex,
                    idLoader.item.dragArea.DelegateModel.itemsIndex)
        }
    }
}

1 Ответ

0 голосов
/ 11 декабря 2018

Элементы, определенные в файле, загруженном с помощью Loader, или вообще в любом другом импортируемом файле .qml, не должны напрямую зависеть от основного файла, так как идентификаторы имеют область действия, в вашем случае лучше выставить свойства:

╭------------------------------------------╮
|                   bool held        ------┿--->
|  TestDelegate     string m_text    ------┿--->
|  ============     DelegateModel md ------┿--->
|                   int index        ------┿--->
╰------------------------------------------╯

Учитывая вышеизложенное, решение состоит в следующем:

main.qml

import QtQuick 2.7
import QtQuick.Window 2.0
import QtQml.Models 2.3

Window {
    id: mainroot
    visible: true
    width: 640
    height: 480

    Rectangle{
        id:viewContainer
        anchors.fill: parent

        DelegateModel {
            id: visualModel
            model: ListModel{
                id:m_model
                Component.onCompleted: {
                    for(var i=0; i< 40; i++){
                        m_model.append({"type": 1, "m_text": "Text" + i})
                    }
                }
            }
            delegate:
                Loader{
                id: idLoader
                width: view.width
                height: childrenRect.height
                property int index: DelegateModel.itemsIndex
                onIndexChanged: if(status == Loader.Ready) idLoader.item.index = index
                Component.onCompleted: {
                    switch(type){
                    case 1:
                        idLoader.setSource("TestDelegate.qml", {
                                               "m_text": m_text,
                                               "index": index,
                                               "md": visualModel
                                           })
                        break;
                    }
                }
            }
        }
        ListView{
            id: view
            anchors.fill: parent
            spacing: 5
            model: visualModel
        }
    }
}

TestDelegate.qml

import QtQuick 2.7
import QtQml.Models 2.3

MouseArea {
    id: dragArea
    property bool held: false
    property string m_text
    property DelegateModel md: null
    property int index : -1;
    anchors { left: parent.left; right: parent.right }
    height: 50
    width: view.width
    drag.target: held ? content : undefined
    drag.axis: Drag.YAxis
    onPressAndHold: held = true
    onReleased: held = false
    Rectangle {
        id: content
        anchors {
            horizontalCenter: parent.horizontalCenter
            verticalCenter: parent.verticalCenter
        }
        width: dragArea.width
        height: textfield.implicitHeight
        Drag.active: dragArea.held
        Drag.source: dragArea
        Drag.hotSpot.x: width / 2
        Drag.hotSpot.y: height / 2
        border.width: 1
        border.color: "lightsteelblue"
        color: dragArea.held ? "lightsteelblue" : "white"
        Behavior on color { ColorAnimation { duration: 100 } }
        radius: 2
        states: State {
            when: dragArea.held
            ParentChange { target: content; parent: viewContainer }
            AnchorChanges {
                target: content
                anchors { horizontalCenter: undefined; verticalCenter: undefined }
            }
        }
        Text{
            id: textfield
            anchors.centerIn: parent
            text: m_text
        }
    }
    DropArea {
        anchors { fill: parent; margins: 10 }
        onEntered: {
            if(md !== null)
                md.items.move(drag.source.index, dragArea.index)
        }
    }
}
...