如何在部分中自动排序QML ListElements?

时间:2015-04-03 09:39:14

标签: qt qml

我有一个ListModel,里面有一些ListElemts。我希望这些元素在ListView中的部分上排序。当我运行时:

Page {
    ListModel {
        id: listModel
        ListElement {
            title: "life"
            section: "a"
        }
        ListElement {
            title: "universe"
            section: "b"
        }
        ListElement {
            title: "and everything"
            section: "a"
        }
    }
    ListView {
        model: listModel
        section {
            property: 'section'
            delegate: SectionHeader {
                text: section
            }
        }
        delegate: ListItem {
            Label {
                text: model.title
            }
        }
    }
}

它提供了类似的内容:

        a
life
        b
universe
        a
and everything

但是我希望它返回类似的内容:

        a
life
and everything
        b
universe

我可以通过按上述顺序在模型中排列ListElements来手动实现这一点,但由于ListElements是动态的,因此这并不完美。 如何确保ListElements按照我想要的方式自动排序?

3 个答案:

答案 0 :(得分:1)

您可以定义一个函数sortModel并在Component.onCompleted

中调用
ListModel {
    id: listModel

    ListElement {
        title: "life"
        section: "a"
    }
    ListElement {
        title: "universe"
        section: "b"
    }
    ListElement {
        title: "and everything"
        section: "a"
    }

    function sortModel()
    {
        for(var i=0; i<count; i++)
        {
            for(var j=0; j<i; j++)
            {
                if(get(i).section == get(j).section)
                    move(i,j,1)
                break
            }
        }
    }

    Component.onCompleted: sortModel()
}

答案 1 :(得分:0)

对于使用部分,您必须创建Qstandart项模型并设置sortRole(section)并将项附加到qstandard项,并将项附加到模型。之后,您必须设置model-> sort(column)函数对模型进行排序。

查看以下代码:

和c ++代码将是: 你有这样的模型课

#include <QStandardItemModel>

enum TypeContact
{
    TitleRole = Qt::UserRole + 1,
    SectionRole = Qt::UserRole + 2,

};

class MyModel : public QStandardItemModel
{
    Q_OBJECT

public:

    MyModel(QObject *parent = 0)
    : QStandardItemModel(parent)
    {
    }


protected:
    QHash<int, QByteArray> roleNames() const
    {
        QHash<int, QByteArray> m_roles;

        m_roles[TitleRole] = "titleRole";
        m_roles[SectionRole] = "sectionRole";

        return m_roles;
    }
};

以及在另一个类中以及要在其中添加数据以进行模型编写的位置:

//in .h file
QStandardItemModel *model {nullptr};    

//.in .cpp file
model = new MyModel(this);
model->clear();
model->setSortRole(sectionRole);

然后插入您的数据。

QStandardItem *item = new QStandardItem;
item->setData( "life", titleRole);
item->setData( "a", sectioRole);
model->appedRow(item);

QStandardItem *item2 = new QStandardItem;
item2->setData( "universal", titleRole);
item2->setData( "b", sectioRole);
model->appedRow(item2);

QStandardItem *item3 = new QStandardItem;
item3->setData( "and every think", titleRole);
item3->setData( "a", sectioRole);
model->appedRow(item3);

并像这样排序模型:

model->sort(0);

qml代码将为:

ListView {
    anchors.fill: parent
    model: MyModel

    delegate: Label {
        text: titleRole
        width: 100
        height: 50
    }

    section.property: "sectionRole"
    section.criteria: ViewSection.FullString
    section.delegate: Label {
        text: section
        font.bold: true
        font.pixelSize: 25
    }
}

我没有完全测试它,但是它必须可以工作。如果您搜索有关Qstandard项目模型以及如何将其附加到模型并将其设置为模型的信息,则您完全知道必须执行的操作。但是这里setSortRole()和sort()的重要性是。

谢谢

答案 2 :(得分:0)

在这个答案中,我使用Array.protoype.sort()对列表模型进行排序。

    var indexes = new Array(listModel.count);
    for (var i = 0; i < listModel.count; i++) indexes[i] = i;
    console.log(JSON.stringify(indexes)); // [0,1,2]
    indexes.sort(function (a, b) { return compareFunc(listModel.get(a), listModel.get(b)); } );
    console.log(JSON.stringify(indexes)); // [0,2,1]
    var sorted = 0;
    while (sorted < indexes.length && sorted === indexes[sorted]) sorted++;
    console.log(sorted); // 1
    if (sorted === indexes.length) return;
    for (i = sorted; i < indexes.length; i++) {
        var index = indexes[i];
        listModel.move(index, listModel.count - 1, 1);
        listModel.insert(index, { } );
    }
    listModel.remove(sorted, indexes.length - sorted);

以上算法的工作原理:

  1. 创建一个与列表模型大小相同的整数数组。
  2. 使用Array.protoype.sort()和经过修改的compare函数对数组重新排序
  3. 然后,使用排序后的索引,将其应用于listModel,根据需要对元素进行重新排序

以下是OP数据集的有效答案:

Page {
    width: 800
    height: 480
    ListModel {
        id: listModel
        ListElement {
            title: "life"
            section: "a"
        }
        ListElement {
            title: "universe"
            section: "b"
        }
        ListElement {
            title: "and everything"
            section: "a"
        }
    }
    ListView {
        id: listView
        anchors.fill: parent
        model: listModel
        section {
            property: 'section'
            delegate: ItemDelegate {
                text: section
                font.pointSize: 12
            }
        }
        delegate: ItemDelegate {
            text: model.title
            font.pointSize: 10
        }
    }
    function listModelSort(listModel, compareFunc) {
        var indexes = new Array(listModel.count);
        for (var i = 0; i < listModel.count; i++) indexes[i] = i;
        console.log(JSON.stringify(indexes)); // [0,1,2]
        indexes.sort(function (a, b) { return compareFunc(listModel.get(a), listModel.get(b)); } );
        console.log(JSON.stringify(indexes)); // [0,2,1]
        var sorted = 0;
        while (sorted < indexes.length && sorted === indexes[sorted]) sorted++;
        console.log(sorted); // 1
        if (sorted === indexes.length) return;
        for (i = sorted; i < indexes.length; i++) {
            var index = indexes[i];
            listModel.move(index, listModel.count - 1, 1);
            listModel.insert(index, { } );
        }
        listModel.remove(sorted, indexes.length - sorted);
    }
    function compareElements(elem1, elem2) {
        return elem1.section.localeCompare(elem2.section);
    }
    Component.onCompleted: listModelSort(listModel, compareElements)
}