从另一个模型中提取子模型?

时间:2016-01-26 22:25:03

标签: c++ qt qml

以下代码来自Qt演示。这是QTreeView的模型。

下面的

TreeItem类表示树中的每个节点,它可以有子节点。

class TreeItem
{
public:
    explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = 0);
    ~TreeItem();

    void appendChild(TreeItem *child);

    TreeItem *child(int row);
    int childCount() const;
    int columnCount() const;
    QVariant data(int column) const;
    int row() const;
    TreeItem *parentItem();

private:
    QList<TreeItem*> m_childItems;
    QList<QVariant> m_itemData;
    TreeItem *m_parentItem;
};
下面的

TreeModel类是主要模型。它只包含一个包含所有其他子节点的根节点。

class TreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    explicit TreeModel(const QString &data, QObject *parent = 0);
    ~TreeModel();

    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
    Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;

private:
    void setupModelData(const QStringList &lines, TreeItem *parent);

    TreeItem *rootItem;
};

我正在使用QML,我可以在树中显示此模型,但我也希望以ListView显示。

对于ListView,我只想一次显示一个层(第一个孩子)。当用户点击任何一个项目时,它应该清除并显示该项目的子项。我该怎么做?

我的Qml代码如下。它显示所有第一层孩子,这很棒,但我需要在用户点击某个项目时显示孩子。我的想法是需要提取子模型并指向它,但是如何?

Item {
    width: parent.width
    height: parent.height

    ListView {
        //anchors.top: myImage.bottom
        anchors.fill: parent
        id: list
        spacing: 4
        model: treeModel

        delegate: listDelegate

    }

    Component {
        id: listDelegate
        Rectangle
        {
            id: delegateRect
            height: image.height
            width: 500
            Image {
                id: image
                source: "qrc:/icons/resources/element.ico"

            }

            Text {
                id: t
                anchors.left: image.right
                anchors.leftMargin: 20
                anchors.centerIn: delegateRect

                text: title + "/" + summary
                //text: display
            }

            MouseArea {
                anchors.fill: parent
                onClicked: {

                    list.currentIndex = index

                    console.log("Item clicked, index = " + index)

                    // I think I should change model here to sub model but how do I do it?
                    //list.model = treeModel.data(index) 
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您应该查看Qt文档http://doc.qt.io/qt-5/qabstractproxymodel.html中的QAbstractProxyModel和派生类。

代理模型用于映射模型索引(如果要修改布局,或对数据进行排序/过滤)并进行数据处理(修改源模型数据方法返回的数据)。

您需要做的是添加一个属性来选择 new root (应该是提取模型的根项的项)并实现两个方法mapFromSource(const QModelIndex &)mapToSource(const QModelIndex &)。这些方法将给予视图的模型索引(仅在代理模型中有效)映射到基于当前设置的 root 属性对源模型有效的模型索引(反之亦然)。

此外,您还应重新实现roleNames()方法,以转发源模型定义的角色名,以便能够从QML内部访问数据。