QT----基于QML的计时器

赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库,可以对比文档和提交记录学习起来更清晰
QT-Timer

file
file

file
file

学习使用c++的listmodel

学习使用了如何用c++的listmodel来存储数据.

新建一个TImeListModel类继承自QAbstractListModel

class TimeListModel : public QAbstractListModel
{
   
    
    
    Q_OBJECT
public:
    explicit TimeListModel(QObject *parent = nullptr);

创建一个结构体存储数据对,在用一个列表存储所有的数据,这个datalist就是listview

private:
    // 定义一个结构体来存储列表项的数据,包括 idnumber 和 timeStr
    struct Data{
   
    
    
        QString m_idnumber; // 存储编号
        QString m_timeStr;  // 存储时间字符串
    };

    // 使用 QList 来存储所有 Data 结构体的数据
    QList<Data> m_datalist;

然后重写三个函数,这三个函数是必须重写的,直接复制就行,都不用改.在定义一个枚举以便 QML 通过这些角色从模型中获取数据。具体来说,NumberRoleTimerRole 代表不同的数据属性,能够让 ListView 或其他基于模型的视图组件根据这些角色来访问对应的字段。


// 返回模型中数据的总数,用于 ListView 获取到数据的数量
    // 这个函数是 QAbstractListModel 的纯虚函数,必须实现
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    // 返回模型的角色名称,用于在 QML 中根据角色访问数据
    // 例如,NumberRole 对应的别名可以被 ListView 使用
    virtual QHash<int, QByteArray> roleNames() const override;

    // 获取指定行和角色的数据,这个函数会在 ListView 渲染数据时被调用
    // 数据是从 QList 中的 Data 结构体获取的
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

// 枚举角色,用于指定 QML 中访问数据的键值
    // NumberRole 和 TimerRole 允许 QML 中根据不同的键来访问数据
    enum DataRoles{
   
    
    
        NumberRole = Qt::UserRole + 1, // 用户自定义的角色从 Qt::UserRole 开始
        TimerRole,                     // 时间角色
    };

重写这三个函数的实现,根据你的数据直接抄就行,数据的个数与结构体和枚举对应

rowCount获取列表里元素的个数

roleNames设置角色与对应的名称,这样可以在qml使用model.m_idnumber来访问列表元素的idnumber

data用于获取索引和角色的数据

// 返回列表项的数量,用于 ListView 知道有多少项要显示
int TimeListModel::rowCount(const QModelIndex &parent) const
{
   
    
    
    // 返回数据列表的大小
    return m_datalist.size();
}

// 定义数据角色的名称映射,用于在 QML 中使用这些角色名称来访问数据
QHash<int, QByteArray> TimeListModel::roleNames() const
{
   
    
    
    // 设置角色与对应的名称,这样可以在 QML 中通过 "m_idnumber" 和 "m_timeStr" 获取对应的数据
    QHash<int,QByteArray> roles;
    roles[NumberRole] = "m_idnumber"; // 角色 NumberRole 对应 m_idnumber
    roles[TimerRole] = "m_timeStr";   // 角色 TimerRole 对应 m_timeStr
    return roles;
}

// 获取指定索引行和角色的数据,用于 ListView 显示数据
QVariant TimeListModel::data(const QModelIndex &index, int role) const
{
   
    
    
    int row = index.row(); // 获取当前索引的行号

    // 检查索引是否有效,避免访问越界
    if(row < 0 || row >= m_datalist.count()) {
   
    
    
        return QVariant(); // 返回无效数据
    }

    // 获取当前行对应的数据
    const Data &data = m_datalist[row];

    // 根据传入的角色返回不同的数据
    switch(role) {
   
    
    
    case NumberRole:
        return data.m_idnumber;  // 返回编号数据
    case TimerRole:
        return data.m_timeStr;   // 返回时间字符串数据
    default:
        return QVariant();       // 返回空值
    }
}

除了三个必须重写的函数,一般我们会添加一个增加数据 append和删除数据的函数,我这边直接清空就行使用 clear.将这两个函数暴露给QML,使用 Q_INVOKABLE添加上这个后,这两个函数可以在qml中调用

// Q_INVOKABLE 使得这些方法可以从 QML 中被调用
    // append 函数用于向模型中添加数据,接收 idnumber 和 timeStr 两个字符串
    Q_INVOKABLE void append(const QString &idnumber , const QString &timeStr);

    // 清空模型中的所有数据
    Q_INVOKABLE void clear();

实现这两个函数,添加数据时需要发送信号,添加时发送,添加完成发送,这样listView会在界面上实时刷新,如果想插入到末尾,发送信号位置是开始位置m_datalist.lastIndexOf(),结束位置也是

// 向数据列表中添加一项新数据
void TimeListModel::append(const QString &idnumber, const QString &timeStr)
{
   
    
    
    // 通知视图模型即将插入一行新数据,索引 0 表示新数据会插入到列表的最前面
    emit beginInsertRows(QModelIndex(), 0, 0);

    // 使用 prepend 将新的 Data 结构体添加到列表的开头
    m_datalist.prepend({
   
    
    idnumber, timeStr})

猜你喜欢

转载自blog.csdn.net/szn1316159505/article/details/142355017
今日推荐