具有更改模型的ListView的QML GridView

时间:2018-07-09 16:15:07

标签: qt listview model qml

我花了几天时间解决这个问题。为了简便起见,我制作了一个小样本。

这是我的代码。

  1. main.cpp和模型类
  2. main.qml
  3. ListComponent.qml

如您所见,在ListComponent.qml中,我有一个与后端模型绑定的listview。 因此,我在main.qml和模型中制作了2个ListComponent.qml实例。

我的要求是,如果我在cpp中有一个MassDataList,其中包含人员名称, 在ListView1中,我都需要以字母A开头;在ListView2中,我都需要以字母B开头。

代码示例如下:

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")

TextField {
x: 0
y: 0
onTextChanged: Test.setModel(text)

}

ListComponent {
id: component1
x: 26
y: 44
width: 100
height: 291
}

ListComponent {
id: component2
x: 163
y: 44
width: 100
height: 291
}
}

ListComponent.qml

import QtQuick 2.0

Item {
Rectangle {
id: rectangle
color: "#ffffff"
anchors.fill: parent

ListView {
id: listView
width: 200; height: 300
spacing: 5
model: Test.model
anchors.fill: parent
delegate: Item {
x: 5
width: 80
height: 40
Row {
id: row1
spacing: 10
Text {
text: modelData
font.bold: true
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}

}

C ++方面

TestModel-Test.h

#ifndef TEST_H
    #define TEST_H
    #include "QObject"

    class Test: public QObject {
        Q_OBJECT
           Q_PROPERTY(QStringList model MEMBER m_model NOTIFY modelChanged)
           QStringList m_model;
         public slots:
           void setModel(QString m) {
               QStringList q;
               for(int i=0;i<massList.length();i++)
               {
                   if(massList.at(i).contains(m))
                       q.append(massList[i]);
               }
             //m_model = m.split(" ");

               m_model = q;
             modelChanged();
           }
         signals:
           void modelChanged();
    public:
           Test();
           QList<QString> massList;
       };
    #endif // TEST_H

Test.cpp

#include "test.h"

Test::Test()
{
  massList.append("Anil");
  massList.append("Athul");
  massList.append("Aneesh");
  massList.append("Ajay");
  massList.append("Anoop");

  massList.append("Bithu");
  massList.append("Bineesh");
  massList.append("Bineesh");
  massList.append("Bejoy");
  massList.append("Anirudh");

}

最后是main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "test.h"
#include "QQmlContext"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    Test t;
    engine.rootContext()->setContextProperty("Test", &t);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;


    return app.exec();
}

请帮助

根据Eyllanesc的建议,我尝试了以下示例中的代表小组。但是问题在于,对于每个过滤器,我需要创建不同的模型组。就我而言,这是不可能的。

我有一个GridView,其中ListViews作为委托项,并且我想要用于不同listViews的不同模型。

这是我尝试的示例委托组示例

/*
 * Copyright 2014 ImaginativeThinking
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0
import QtQml.Models 2.1
import QtQml.Models 2.1

ApplicationWindow {
    title: qsTr("DelegateModel Sample 2")
    width: 640
    height: 600
    visible: true
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }

    Item {
        id: root
        anchors.fill: parent
        readonly property int rowHeight: 25

        DelegateModel {
            id: detailsDelegateModel
            delegate: detailsDelegate
            model: MyModel // This is a root context set in the main.cpp file.
            groups: [
                DelegateModelGroup {
                    includeByDefault: false
                    name: "detailsField"
                }
            ]
            filterOnGroup: "detailsField"
            Component.onCompleted: {
                var rowCount = MyModel.count;
                items.remove(0,rowCount);
                for( var i = 0;i < rowCount;i++ )
                {
                    var entry = MyModel.get(i);
                    if(entry.role_details !== undefined) {
                        items.insert(entry, "detailsField");
                    }
                }
            }
        }
        Component {
            id: detailsDelegate

            Rectangle {
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight
                color: "yellow"
                border.color: "black"

                Text {
                    text: role_details
                    anchors.centerIn: parent
                }
            }
        }
        DelegateModel {
            id: displayDelegateModel
            delegate: displayDelegate
            model: MyModel
            groups: [
                DelegateModelGroup {
                    includeByDefault: false
                    name: "displayField"
                }
            ]
            filterOnGroup: "displayField"
            Component.onCompleted: {
                var rowCount = MyModel.count;
                items.remove(0,rowCount);
                for(var i = 0;i < rowCount;i++)
                {
                    var entry = MyModel.get(i);
                    if(entry.role_display !== undefined){
                        items.insert(entry, "displayField");
                    }
                }
            }
        }
        Component{
            id: displayDelegate

            Rectangle {
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight
                color: "green"
                border.color: "black"

                Text {
                    text: role_display
                    anchors.centerIn: parent
                }
            }
        }
        DelegateModel {
            id: evenValueDelegateModel
            delegate: valueDelegate
            model: MyModel
            groups: [
                DelegateModelGroup {
                    includeByDefault: false
                    name: "evenNumbers"
                }
            ]
            filterOnGroup: "evenNumbers"
            Component.onCompleted: {
                var rowCount = MyModel.count;
                items.remove(0,rowCount);
                for( var i = 0;i < rowCount;i++ )
                {
                    if ( MyModel.isEven(i) ) {
                        items.insert(MyModel.get(i), "evenNumbers");
                    }
                }
            }
        }
        Component{
            id: valueDelegate

            Rectangle {
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight
                color: "lightblue"
                border.color: "black"

                Text {
                    text: role_value
                    anchors.centerIn: parent
                }
            }
        }
        Column{
            id: theColumn
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.top: parent.top
            anchors.margins: 10
            height: childrenRect.height
            spacing: 0

            Text {
                anchors.horizontalCenter: parent.horizontalCenter
                width: 600
                wrapMode: Text.WordWrap
                text: "In this example we have a single model with 12 entries and via a Delegate Model Group we are filtering that data so that we can display a sub-set of it in different ListViews"
            }
            Item { width: 20; height: 20; }
            Text {
                text: "In this List View we are only showing the entries that have a details role."
            }
            ListView {
                id: detailsListView
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight * 5
                model: detailsDelegateModel
            }
            Item { width: 20; height: 20; }
            Text {
                text: "In this List View we are only showing the entries that have a display role."
            }
            ListView {
                id: displayListView
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight * 4
                model: displayDelegateModel
            }
            Item { width: 20; height: 20; }
            Text {
                text: "In this List View we are only showing the entries whose value are even."
            }
            ListView {
                id: evenValueListView
                anchors.left: parent.left
                anchors.right: parent.right
                height: root.rowHeight * 7
                model: evenValueDelegateModel
            }
        }
    }
}

具有以下型号。

标题为

/*
 * Copyright 2014 ImaginativeThinking
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MYVIEWMODEL_H
#define MYVIEWMODEL_H

#include <QStandardItemModel>
#include <QObject>

class MyViewModel : public QStandardItemModel
{
    Q_OBJECT
    Q_PROPERTY( int count READ getRowCount() NOTIFY rowCountChanged() )

public:
    /**
     * @brief Defines a list of application-specific roles particually related to this view model's data model.
     *
     * Each item in the view model has a set of data elements associated with it, each with its own role.
     * Roles are used by the view to indicate to the view model which type of data it needs.  The roles
     * defined in this enum are specific to this view models data model.
     * @see <a href="http://qt-project.org/doc/qt-5.0/qtcore/qt.html#ItemDataRole-enum" style="font-weight:bold;">Qt::ItemDataRole</a>
     */
    enum MyViewModel_Roles
    {
        MyViewModel_Roles_Display = Qt::UserRole + 1,   /**< This role holds the display string for an entry in the model. */
        MyViewModel_Roles_Details,                      /**< This role holds the details string for an entry in the model. **/
        MyViewModel_Roles_KeyId,                        /**< This role holds the key id for an entry in the model. **/
        MyViewModel_Roles_Value,                        /**< This role holds the value for an entry in the model. **/
    };

    /**
     * @brief MyViewModel is the Constructor that will create an instance of this class
     */
    MyViewModel();

    /**
     * @brief ~MyViewModel is the destructor that will clean up this object when its not needed anymore.
     */
    virtual ~MyViewModel();

    /**
     * @brief Initializes the ViewModel and populates it with data
     */
    void initialize();

    /**
     * @return A collection of the view models role names.
     * @see MenuRoles
     * @see <a href="http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#roleNames" style="font-weight:bold;">QAbstractItemModel</a>
     */
    virtual QHash<int,QByteArray> roleNames() const;

    /**
     * @param rowNumber is the index within the model for the item we want to check.
     * @return Returns true if the entry's value role holds an even number.
     */
    Q_INVOKABLE bool isEven( int rowNumber );

    /**
     * @param rowNumber specifies which row within the model the item we want to check is located.
     * @return Returns a map that holds all the attributes about the item using the role names as the key.
     * @note The return value is a key/value pair where the keys are available in QML so we can
     * use the returned object to get any of the role information about the data (e.g. returnObject.role_display)
     */
    Q_INVOKABLE QVariantMap get( int rowNumber ) const;

signals:

    /**
     * @brief rowCountChanged is emitted whenever the row count changes
     */
    void rowCountChanged();

private slots:
    /**
     * @return Returns the number of rows in the model
     */
    int getRowCount();

};

#endif // MYVIEWMODEL_H

cpp是

#include "MyViewModel.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MyViewModel::MyViewModel()
{
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MyViewModel::~MyViewModel()
{
    this->clear();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QHash<int,QByteArray> MyViewModel::roleNames() const
{
    // Maps the role names used in the QML to the role name enum used in the code behind.

    QHash<int, QByteArray> roles;
    roles[MyViewModel_Roles_Display] = "role_display";
    roles[MyViewModel_Roles_Details] = "role_details";
    roles[MyViewModel_Roles_KeyId] = "role_keyid";
    roles[MyViewModel_Roles_Value] = "role_value";

    return roles;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void MyViewModel::initialize()
{
    auto root = this->invisibleRootItem();

    QStandardItem* entry = new QStandardItem();
    entry->setData("One", MyViewModel_Roles_Display );
    entry->setData(0, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("One", MyViewModel_Roles_Display );
    entry->setData(2, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("One", MyViewModel_Roles_Display );
    entry->setData(3, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("One", MyViewModel_Roles_Display );
    entry->setData(4, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Two", MyViewModel_Roles_Details );
    entry->setData(5, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Three", MyViewModel_Roles_Details );
    entry->setData(6, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Four", MyViewModel_Roles_Details );
    entry->setData(7, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Five", MyViewModel_Roles_Details );
    entry->setData(8, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Six", MyViewModel_Roles_Details );
    entry->setData(9, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Seven", MyViewModel_Roles_KeyId );
    entry->setData(10, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("Eight", MyViewModel_Roles_KeyId );
    entry->setData(11, MyViewModel_Roles_Value );
    root->appendRow(entry);

    entry = new QStandardItem();
    entry->setData("hello", MyViewModel_Roles_KeyId );
    entry->setData(12, MyViewModel_Roles_Value );
    root->appendRow(entry);

    emit rowCountChanged();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int MyViewModel::getRowCount()
{
    return this->rowCount();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool MyViewModel::isEven(int rowNumber)
{
    bool ret( false );
    if ( this->invisibleRootItem() != nullptr )
    {
        if ( this->invisibleRootItem()->rowCount() > rowNumber )
        {
            auto entry = this->invisibleRootItem()->child( rowNumber );
            bool ok( false );
            auto value = entry->data( MyViewModel_Roles::MyViewModel_Roles_Value ).toInt( &ok );
            if ( ok )
            {
                if ( ( value % 2) == 0 )
                {
                    ret = true;
                }
            }
        }
    }
    return ret;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QVariantMap MyViewModel::get( int rowNumber ) const
{
    // Create a map to hold all the role information about the data item in question
    // Use the role names as the keys for the map so that the same referances can be
    // used in the QML to get the data (i.e. role_display, role_value).
    QVariantMap map;
    QHash<int,QByteArray> roleName = roleNames();
    foreach (int i, roleName.keys())
    {
        map[roleName.value(i)] = data( index( rowNumber,0 ), i );
    }
    return map;
}

1 个答案:

答案 0 :(得分:0)

我使用提到的FilterGroups解决了这个问题。问题解决了。管理员,如何将其标记为已解决?