QML学习笔记4(qml ListView QAbstractListModel)

1,创建对象实体类
 

//person.h
#ifndef PERSON_H
#define PERSON_H

#include <QObject>

class Person : public QObject
{
    Q_OBJECT
public:
    Person(QString name,int age, QObject *parent = nullptr);
    Person(QObject *parent = nullptr);
    QString getName() const;
    void setName(const QString &value);

    int getAge() const;
    void setAge(int value);

    int getID() const;
    void setID(int value);

private:
    QString Name;
    int Age;
    int ID;
};

#endif // PERSON_H
//person.cpp
#include "person.h"

Person::Person(QString name,int age,QObject *parent) : QObject(parent)
{
    Name=name;
    Age=age;
}

Person::Person(QObject *parent): QObject(parent)
{

}

QString Person::getName() const
{
    return Name;
}

void Person::setName(const QString &value)
{
    Name = value;
}

int Person::getAge() const
{
    return Age;
}

void Person::setAge(int value)
{
    Age = value;
}

int Person::getID() const
{
    return ID;
}

void Person::setID(int value)
{
    ID = value;
}

 2,创建基于QAbstractListModel的数据列表
 

//personlistviewmodel.h
#ifndef PERSONLISTVIEWMODEL_H
#define PERSONLISTVIEWMODEL_H

#include <QObject>
#include <QAbstractListModel>
#include <QVariant>
#include "person.h"
#include "sqlitehelper.h"
#include "sqlite3.h"

class PersonListViewModel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit PersonListViewModel(SQLiteHelper *sqlhelper,QObject *parent = nullptr);
    ~PersonListViewModel();
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const ;
    virtual QHash<int, QByteArray> roleNames() const ;
    virtual int rowCount(const QModelIndex &parent = QModelIndex())  const ;
    bool setData(const QModelIndex &index, const QVariant &value, int role) override;


    int InsertPerson(Person *person);
    void deletePerson(int id);
    Q_INVOKABLE void updataPerson(int id, QString name, int age);
    Person* SelectPerson(int id);
    QList<Person*> getAllPerson();
    QList<Person*> personList;

private:
    enum DataRoles{
        NameRole,
        AgeRole,
        IDRole
    };

    SQLiteHelper *sqlHelper;
public slots:
    void  addItem(QString name,int age);
    void  deleteItem(int id);
};

#endif // PERSONLISTVIEWMODEL_H
//personlistviewmodel.cpp
#include "personlistviewmodel.h"

PersonListViewModel::PersonListViewModel(SQLiteHelper *sqlhelper, QObject *parent)
{
    Q_UNUSED(parent);
    sqlHelper=sqlhelper;

    //创建数据库
    char *errmsg;      //出错信息
    const char *createPerson="create table IF NOT EXISTS Person("
                             "ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
                             "Name varchar(30) NOT NULL, "
                             "Age int NOT NULL"
                             ");";
    int res = sqlite3_exec(sqlHelper->sqldb, createPerson, NULL, NULL, &errmsg);
    if(res!=SQLITE_OK)
    {
        qDebug()<<"创建Person表失败:"<<sqlite3_errcode(sqlHelper->sqldb)<<endl;
        qDebug()<<"创建Person表失败:"<<sqlite3_errmsg(sqlHelper->sqldb)<<endl;
        qDebug()<<"创建Person表失败:"<<errmsg;
        sqlite3_free(errmsg);
    }

    personList=getAllPerson();
}

PersonListViewModel::~PersonListViewModel()
{
    qDebug()<<"free person manage";
}

QVariant PersonListViewModel::data(const QModelIndex &index, int role) const
{
    switch(role){
    case  DataRoles::IDRole : return personList[index.row()]->getID();
    case  DataRoles::AgeRole : return personList[index.row()]->getAge();
    case  DataRoles::NameRole : return personList[index.row()]->getName();
    default : break ;
    }
    return QVariant();
}

QHash<int, QByteArray> PersonListViewModel::roleNames() const
{
    QHash <int,QByteArray> temp ;
    temp.insert(DataRoles :: IDRole,"id");
    temp.insert(DataRoles :: AgeRole,"age");
    temp.insert(DataRoles :: NameRole,"name");
    return temp ;
}

int PersonListViewModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return personList.length();
}

bool PersonListViewModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int row=index.row();
    int col=index.column();
    auto p=index.parent();
    auto v=value.isValid();
   if (!hasIndex(row,col, p) || !v)
        return false;

    Person *person = personList[index.row()];
    if (role == DataRoles::NameRole)
    {
        person->setName(value.toString());
    }
    else if (role == DataRoles::AgeRole)
    {
        person->setAge(value.toString().toInt());
    }
    else
    {
        return false;
    }

    emit dataChanged(index, index, { role } );

    return true ;
}

int PersonListViewModel::InsertPerson(Person *person)
{
    char *errmsg;
    QString insertPerson=QString("INSERT INTO Person(NAME,AGE) VALUES('%1', %2)").arg(person->getName()).arg(person->getAge());
    int res=sqlite3_exec(sqlHelper->sqldb, insertPerson.toUtf8(), NULL, NULL, &errmsg);
    if(res!=SQLITE_OK)
    {
        qDebug()<<sqlite3_errcode(sqlHelper->sqldb)<<endl;
        qDebug()<<sqlite3_errmsg(sqlHelper->sqldb)<<endl;
        qDebug()<<errmsg;
        sqlite3_free(errmsg);
        return -1;
    }
    else
    {
        char * zErrMsg = NULL;      //错误信息指针的地址
        char ** pResult = NULL;     //用来指向sql执行结果的指针
        int nrow = 0;               //满足条件的记录数目
        int ncolumn = 0;            //每条记录包含的字段数据
        QString selectPerson= "SELECT * FROM Person order by ID desc";
        int result = sqlite3_get_table(sqlHelper->sqldb, selectPerson.toUtf8(), &pResult, &nrow, &ncolumn, &zErrMsg);
        if(result==SQLITE_OK)
        {
            return  sqlHelper->getIntValue(pResult,ncolumn,0,0);
        }
        else
        {
            return  -1;
        }
    }
}

void PersonListViewModel::deletePerson(int id)
{
    char *errmsg;
    QString insertPerson=QString("DELETE FROM Person WHERE ID=%1").arg(id);
    int res=sqlite3_exec(sqlHelper->sqldb, insertPerson.toUtf8(), NULL, NULL, &errmsg);
    if(res!=SQLITE_OK)
    {
        qDebug()<<sqlite3_errcode(sqlHelper->sqldb)<<endl;
        qDebug()<<sqlite3_errmsg(sqlHelper->sqldb)<<endl;
        qDebug()<<errmsg;
        sqlite3_free(errmsg);
    }
    qDebug()<<"delete updata";
}

void PersonListViewModel::updataPerson(int id, QString name, int age)
{
    char *errmsg;
    QString insertPerson=QString("UPDATE Person SET NAME = '%1',Age = %2 WHERE ID = %3").arg(name).arg(age).arg(id);
    int res=sqlite3_exec(sqlHelper->sqldb, insertPerson.toUtf8(), NULL, NULL, &errmsg);
    if(res!=SQLITE_OK)
    {
        qDebug()<<sqlite3_errcode(sqlHelper->sqldb)<<endl;
        qDebug()<<sqlite3_errmsg(sqlHelper->sqldb)<<endl;
        qDebug()<<errmsg;
        sqlite3_free(errmsg);
    }
    else
    {
        if(personList.count()>0)
        {
            qDebug()<<"ID"<<id;
            for(int i=0;i<personList.size();i++)
            {
                if(personList[i]->getID()==id)
                {
                    if(personList[i]->getAge()!=age)
                    {
                        setData(this->index(i) ,age,DataRoles::AgeRole);
                    }
                    if(personList[i]->getName()!=name)
                    {
                        setData(this->index(i),name,DataRoles::NameRole);
                    }

                    //personList.replace(i,personList[i]); //beginRemoveRows(QModelIndex(),i,i);


                    //endRemoveRows();
                    break;
                }
            }
        }
    }
}

Person *PersonListViewModel::SelectPerson(int id)
{
    char * zErrMsg = NULL;      //错误信息指针的地址
    char ** pResult = NULL;     //用来指向sql执行结果的指针
    int nrow = 0;               //满足条件的记录数目
    int ncolumn = 0;            //每条记录包含的字段数据
    QString selectPerson= QString("SELECT * FROM Person WHERE ID=%1").arg(id);
    int result = sqlite3_get_table(sqlHelper->sqldb, selectPerson.toUtf8(), &pResult, &nrow, &ncolumn, &zErrMsg);
    if(SQLITE_OK != result)
    {
        printf("执行sql语句失败\n");
        return nullptr;
    }
    else
    {
        Person *person=new Person;
        person->setID(sqlHelper->getIntValue(pResult,ncolumn,0,0));
        person->setName(sqlHelper->getQStringValue(pResult,ncolumn,0,1));
        person->setAge(sqlHelper->getIntValue(pResult,ncolumn,0,2));
        sqlite3_free_table(pResult);
        return  person;
    }
}

QList<Person *> PersonListViewModel::getAllPerson()
{
    QList<Person*> persons;
    char * zErrMsg = NULL;      //错误信息指针的地址
    char ** pResult = NULL;     //用来指向sql执行结果的指针
    int nrow = 0;               //满足条件的记录数目
    int ncolumn = 0;            //每条记录包含的字段数据
    QString selectPerson= QString("SELECT * FROM Person");
    int result = sqlite3_get_table(sqlHelper->sqldb, selectPerson.toUtf8(), &pResult, &nrow, &ncolumn, &zErrMsg);
    if(SQLITE_OK != result)
    {
        qDebug()<<"执行sql语句失败"<<endl;
    }
    else
    {
        for(int i=0;i<nrow;i++)
        {
            Person *person=new Person;
            person->setID(sqlHelper->getIntValue(pResult,ncolumn,i,0));
            person->setName(sqlHelper->getQStringValue(pResult,ncolumn,i,1));
            person->setAge(sqlHelper->getIntValue(pResult,ncolumn,i,2));
            persons.append(person);
        }
        sqlite3_free_table(pResult);
    }
    return persons;
}

void PersonListViewModel::addItem(QString name, int age)
{
    Person *person=new Person(name,age);
    auto count=InsertPerson(person);
    qDebug()<<"count:"<<count;
    person->setID(count);
    beginInsertRows(QModelIndex(),rowCount(),rowCount());
    personList.insert(personList.length(),person);
    endInsertRows();
}

void PersonListViewModel::deleteItem(int id)
{

    deletePerson(id);
    if(personList.count()>0)
    {
        qDebug()<<"ID"<<id;
        for(int i=0;i<personList.size();i++)
        {
            if(personList[i]->getID()==id)
            {
                beginRemoveRows(QModelIndex(),i,i);
                personList.removeAt(i);
                endRemoveRows();
                break;
            }
        }
    }

}

需要注意的地方:

1, 需要实现data,roleNames,rowCount重写

roleNames方法中,id,age,name用来在qml中调用 
temp.insert(DataRoles :: IDRole,"id");
    temp.insert(DataRoles :: AgeRole,"age");
    temp.insert(DataRoles :: NameRole,"name");

2,要实现修改数据,需要重写方法setData方法

3,枚举类,用来关联到实体对象的信息,类似于表格的列
enum DataRoles{
        NameRole,
        AgeRole,
        IDRole
    };

3,注册类并使用

QML学习笔记3(qml注册有参单例)https://blog.csdn.net/dwm88888888/article/details/131327605

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现可拖拽、编辑、选中的ListView可以提升用户交互体验,下面介绍一种实现方法。 1. 定义ListView 首先,我们需要定义一个ListView,用于显示列表项。在ListView中,我们需要指定model、delegate、highlight、onPressed、onPositionChanged等属性。 ``` ListView { id: listView model: ListModel { id: listModel } delegate: Component { id: delegate Rectangle { id: item width: listView.width height: 50 color: "white" border.width: 1 border.color: "black" Text { id: text anchors.centerIn: parent text: model.text } MouseArea { id: mouseArea anchors.fill: parent drag.target: item drag.axis: Drag.XAxis drag.minimumX: -listView.width drag.maximumX: listView.width drag.active: listView.currentIndex === index onPressed: { listView.currentIndex = index listView.positionViewAtIndex(index, ListView.Center) } } Rectangle { id: indicator width: 10 height: 10 color: "green" radius: width / 2 visible: listView.currentIndex === index anchors { right: parent.right verticalCenter: parent.verticalCenter margins: 10 } } } } highlight: Rectangle { color: "lightgray" width: listView.width height: 50 border.width: 1 border.color: "black" } onPositionChanged: { if (listView.moving) return; var index = listView.indexAt(listView.contentItem.x, listView.contentItem.y) if (index !== -1 && index !== listView.currentIndex) { listView.currentIndex = index } } } ``` 在上面的代码中,ListView中的delegate定义了每个列表项的展示方式。我们在delegate中定义了一个MouseArea,用于实现可拖拽的功能。在MouseArea的drag.target属性中,我们指定了可拖拽的目标为列表项item。设置drag.axis为Drag.XAxis,表示只能在水平方向上拖拽。设置drag.minimumX为-listView.width,drag.maximumX为listView.width,表示只能在ListView的宽度范围内拖拽。在onPressed事件中,我们设置了当前列表项为选中状态,并将其居中展示。 2. 定义编辑界面 为了实现编辑功能,我们需要定义一个编辑界面。在编辑界面中,用户可以修改列表项的文本内容。我们可以使用一个Dialog来实现编辑界面。 ``` Dialog { id: editDialog title: "Edit Item" modal: true width: 400 height: 200 visible: false TextField { id: textField anchors.centerIn: parent width: parent.width - 40 placeholderText: "Enter item text" } Button { text: "OK" onClicked: { var index = listView.currentIndex if (index !== -1) { listModel.setProperty(index, "text", textField.text) } editDialog.close() } enabled: textField.text !== "" anchors { right: parent.right bottom: parent.bottom margins: 10 } } Button { text: "Cancel" onClicked: editDialog.close() anchors { left: parent.left bottom: parent.bottom margins: 10 } } } ``` 在上面的代码中,我们定义了一个Dialog,其中包含一个TextField和两个Button。用户可以在TextField中输入新的文本内容,然后点击OK按钮保存修改,或点击Cancel按钮取消修改。 3. 实现选中效果 为了让用户能够明显地看到当前选中的列表项,我们可以在每个列表项上添加一个指示器。在ListView的delegate中,我们定义了一个Rectangle,用于显示当前选中的列表项。在Rectangle的visible属性中,我们使用listView.currentIndex === index来判断当前列表项是否被选中。 4. 实现编辑功能 在ListView中,我们可以通过双击或长按来触发编辑功能。在ListView的delegate中,我们为item和mouseArea分别定义了onDoubleClicked和onLongPressed事件。在onDoubleClicked事件中,我们弹出编辑界面,让用户可以修改当前选中的列表项的文本内容。在onLongPressed事件中,我们弹出上下文菜单,让用户可以选择删除当前选中的列表项。 ``` MouseArea { id: mouseArea anchors.fill: parent drag.target: item drag.axis: Drag.XAxis drag.minimumX: -listView.width drag.maximumX: listView.width drag.active: listView.currentIndex === index onPressed: { listView.currentIndex = index listView.positionViewAtIndex(index, ListView.Center) } onDoubleClicked: { editDialog.visible = true textField.text = model.text textField.selectAll() } onLongPressed: { var menu = Menu { MenuItem { text: "Delete" onTriggered: listModel.remove(index) } } menu.popup() } } ``` 在上面的代码中,我们为mouseArea分别定义了onDoubleClicked和onLongPressed事件。在onDoubleClicked事件中,我们弹出编辑界面editDialog,并将当前选中的列表项的文本内容显示在TextField中。在onLongPressed事件中,我们弹出上下文菜单Menu,其中包含一个MenuItem,用于删除当前选中的列表项。 5. 实现拖拽功能 在ListView中,我们可以通过拖拽来调整列表项的顺序。在ListView的delegate中,我们为item定义了onDropped事件。在onDropped事件中,我们交换拖拽的两个列表项的位置。 ``` Rectangle { id: item width: listView.width height: 50 color: "white" border.width: 1 border.color: "black" Text { id: text anchors.centerIn: parent text: model.text } MouseArea { id: mouseArea anchors.fill: parent drag.target: item drag.axis: Drag.XAxis drag.minimumX: -listView.width drag.maximumX: listView.width drag.active: listView.currentIndex === index onPressed: { listView.currentIndex = index listView.positionViewAtIndex(index, ListView.Center) } onDropped: { if (drag.source !== drag.target) { var fromIndex = drag.source.index var toIndex = drag.target.index listModel.move(fromIndex, toIndex, 1) } } } Rectangle { id: indicator width: 10 height: 10 color: "green" radius: width / 2 visible: listView.currentIndex === index anchors { right: parent.right verticalCenter: parent.verticalCenter margins: 10 } } } ``` 在上面的代码中,我们为mouseArea定义了onDropped事件。在onDropped事件中,我们使用ListModel的move方法来交换拖拽的两个列表项的位置。 至此,我们已经实现了可拖拽、编辑、选中的ListView。这个ListView可以让用户方便地调整列表项的顺序,同时也可以让用户快速修改列表项的文本内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值