QT Quick QML 实例之定制 TableView

news2024/11/15 4:09:28

QT Quick QML 实例之定制 TableView

  • 一、演示
  • 二、C++关键步骤
    • 1. beginInsertRows()(用户插入行)
    • 2. roleNames() (表格中列映射)
    • 3. data() (用户获取数据)
    • 4. headerData() (表头)
    • 5. flags (某个单元格的特性标志)
    • 6. setData (用户更新数据)
  • 三、QML UI 显示


所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!

GIT工程源码在这里:     QmlLearningPro编译选择 TableView

QML其它文章请点击这里:     QT QUICK QML 学习笔记


一、演示

● 效果如下:
请添加图片描述

二、C++关键步骤

在Qt中,如使用 QML 的 TableView 并且想要将数据与C++类进行绑定,通常会继承 QAbstractTableModel 来实现自定义的数据模型

1. beginInsertRows()(用户插入行)

beginInsertRows 是 Qt 中的 QAbstractItemModel 类的一部分,用于通知视图 (view) 即将向模型 (model) 中插入行。这个方法通常与 endInsertRows 配对使用,以确保模型的内部数据和视图保持一致。

void MyModel::insertRows(int position, int rows, const QModelIndex &parent = QModelIndex()) {
    // 通知视图即将插入行
    beginInsertRows(parent, position, position + rows - 1);

    // 执行实际的数据插入操作
    // 例如:
    for (int row = 0; row < rows; ++row) {
        dataList.insert(position, newRowData);
    }

    // 通知视图插入行操作已经完成
    endInsertRows();
}

2. roleNames() (表格中列映射)

roleNames() 是 QAbstractItemModel 类中的一个虚函数,通常用于返回模型中的角色(roles)与角色名称(role names)之间的映射。角色在 Qt 的模型-视图框架中用于区分不同类型的数据(例如显示数据、编辑数据、工具提示等)。

//为每个角色提供一个名称,主要用于 QML 绑定。
QHash<int, QByteArray> TargetCoordinate::roleNames() const
{
    QHash<int, QByteArray> roles;

    roles.insert(lngRole,  "lng");
    roles.insert(latRole,  "lat");
    roles.insert(altRole,  "alt");

    return roles;
}

QML 中使用:

	TableViewColumn {
	    role: "lng"   //来源于C++中roleNames
	    title: "Longitude"
	    resizable: true
	}

	TableViewColumn {
	    role: "lat"   
	    title: "Latitude"
	    resizable: true
	}
	
	TableViewColumn {
	    role: "alt"  
	    title: "Altitude"
	    resizable: true
	}

3. data() (用户获取数据)

在 Qt 的 QAbstractItemModel 类中,data() 函数用于返回模型中某个特定项的数据信息。这个函数通常和 roleNames() 函数结合使用,以便为不同的角色返回相应的数据。

视图(如ListView)中请求模型的数据时,视图会调用 data() 函数,并传递相应的 QModelIndex 和 role, data() 函数会根据这些参数返回对应的数据。

QVariant TargetCoordinate::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() < 0 || index.row() >= m_coordinates.count())
        return QVariant();
    const QGeoCoordinate &coordinate = m_coordinates.at(index.row());
    
    switch(role)
    {
        case lngRole:
            return QString::number(coordinate.longitude(), 'f', 6);
        case latRole:
            return QString::number(coordinate.latitude(), 'f', 6);
        case altRole:
            return QString::number(coordinate.altitude(), 'f', 2);
    }
    return QVariant();
}

data() 和 roleNames()关系:

data():提供模型项在特定角色下的数据。
roleNames():为每个角色提供一个名称,主要用于 QML 绑定。

4. headerData() (表头)

headerData() 是 QAbstractItemModel 类中的另一个重要虚函数,用于提供模型的表头信息。在 Qt 的模型-视图框架中,表头用于显示列标题或行标题,通常用于 QTableView、QTreeView 或类似的视图中。

QVariant TargetCoordinate::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();
    /* 当请求的方向为 Qt::Horizontal 时,我们返回与请求的 section(列索引)相关的表头数据。*/
    if (orientation == Qt::Horizontal) {
        if (section == 0)
            return tr("lng");
        else if (section == 1)
            return tr("lat");
        else if (section == 2)
            return tr("alt");
    }
    return QVariant();
}

headerData() 通常与 data() 一起使用,前者用于表头的显示,后者用于表格中具体单元格的显示。

5. flags (某个单元格的特性标志)

flags 用于返回模型中某个项的特性标志(flags)。这些标志指示该项是否可选中、可编辑、可拖放等行为。通过重写 flags() 函数,可以控制模型中每个项的交互行为。

Qt::ItemFlags TargetCoordinate::flags(const QModelIndex &index) const
{
    qDebug() << "flags()" ;

    if (!index.isValid())
        return Qt::NoItemFlags;

    return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}

常见的 Qt::ItemFlag 枚举值:

Qt::NoItemFlags: 表示没有特性,项不可交互。
Qt::ItemIsSelectable: 该项是可选择的。
Qt::ItemIsEditable: 该项是可编辑的。
Qt::ItemIsDragEnabled: 该项支持拖动操作。
Qt::ItemIsDropEnabled: 该项支持放置操作。
Qt::ItemIsUserCheckable: 该项可以显示一个复选框,允许用户进行选择。
Qt::ItemIsEnabled: 该项是可用的(如果未设置,则该项将显示为禁用状态)。

6. setData (用户更新数据)

功能:

编辑数据: 当用户在视图中编辑数据(如在表格单元格中输入文本或选择复选框)时,视图会调用 setData() 函数,模型根据提供的新数据更新相应的项。

拖放操作: 如果支持拖放操作,当数据被放置到模型中的某个位置时,setData() 可能会被调用以插入新数据。

批量数据更新: 你可以在外部批量修改模型的数据,每次修改后调用 setData() 更新特定的项

bool TargetCoordinate::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid() || role != Qt::EditRole)
        return false;

    if (index.row() < 0 || index.row() >= m_coordinates.count())
        return false;

    QGeoCoordinate &coordinate = m_coordinates[index.row()];
    if (index.column() == 0)
        coordinate.setLongitude(value.toDouble());
    else if (index.column() == 1)
        coordinate.setLatitude(value.toDouble());
    else if (index.column() == 2)
        coordinate.setAltitude(value.toDouble());

    //表示仅有一个单元格的数据发生了更改
    emit dataChanged(index, index);
    return true;
}

组合使用
setData() 与 data():setData() 用于更新数据,而 data() 则用于获取数据。视图在显示数据时调用 data(),在用户修改数据时调用 setData()。

flags():在 flags() 函数中设置 Qt::ItemIsEditable 标志,以确保该项可编辑。只有当项是可编辑的,视图才会调用 setData()。

dataChanged 信号:在 setData() 中调用 emit dataChanged(index, index),通知视图相应项的数据已经改变。视图会自动重新绘制受影响的项。

三、QML UI 显示

TableView {
    id: tableView
    anchors.margins:    10
    anchors.fill:       parent
    model:       coordinateModel
    //表格属性
    itemDelegate: {
        return editableDelegate;
    }
    rowDelegate: Rectangle {
        color : styleData.selected ? "#7db9f7" : (styleData.alternate ? "#f5f1f1":"#a89d9d")
        height: 30
    }

    TableViewColumn {
        role: "lng"   //来源于C++中roleNames
        title: "Longitude"
        resizable: true
    }

    TableViewColumn {
        role: "lat"   //y
        title: "Latitude"
//                width: 120
        resizable: true
    }

    TableViewColumn {
        role: "alt"   //
        title: "Altitude"
        resizable: true
    }

    headerDelegate: Rectangle {
        implicitWidth: heardText.width
        implicitHeight: heardText.height * 1.6
        gradient:       styleData.pressed ? pressG : (styleData.containsMouse ? hoverG: normalG)
        border.width: 1
        border.color: "gray"
        Text {
            id:     heardText
            anchors.centerIn: parent
            font.pixelSize: 22
            text:           styleData.value
            color:          styleData.pressed ? "red" : "blue"
            font.bold: true
        }
    }
    
    Component {
        id: editableDelegate
        Rectangle {
            border.color: "gray"
            border.width: 1
            Item{
                anchors.centerIn: parent
                height:  showTXT.height * 1.2
                width:   showTXT.width * 1.2

                Text {
                    id:showTXT
                    anchors.centerIn: parent
                    elide: styleData.elideMode
                    text: styleData.value !== undefined ? styleData.value : ""
                    color: styleData.selected ? "red" : "black"//styleData.textColor
                    font.pixelSize:  18
                    horizontalAlignment: Text.AlignHCenter
                }
            }
        }
    }

    RowLayout {
        anchors.horizontalCenter:   rootRect.horizontalCenter
        anchors.top:                rootRect.bottom
        anchors.topMargin:          20
        Button {
            text:  "add"
            onClicked:      {
     			coordinateModel.insertRowsCoor(tableView.currentRow+1, 1);

                tableView.currentRow = tableView.currentRow + 1
                tableView.refreshTableView
            }
        }
        Button {
            text:  "delete"
            onClicked:      {
                if(tableView.rowCount ===0)  return

                if(tableView.currentRow === -1)    coordinateModel.removeRowsCoor(tableView.currentRow-1);
                else    coordinateModel.removeRowsCoor(tableView.currentRow);

                tableView.refreshTableView
            }
        }
    }

具体代码见工程源码


GIT 工程文件点击这里:     QmlLearningPro编译选择 TableView

QML 其它文章请点击这里:     QT QUICK QML 学习笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04后适配SONY索尼的HDMI OUT的机芯8530

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04后适配SONY索尼的HDMI OUT的机芯8530 2024/8/24 16:33 echo 8 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio8/direction echo 1 > /sys/class/gpio/gpio8/value 1、HDMI IN 4K 2024/7/25 18:01 v4l2-ctl -…

文件—python

一、文件编码 对于同一份文件&#xff0c;人的视角和计算机的视角是不相同的&#xff0c;人看到的是文字&#xff0c;计算机看到的0和1组成的编码。因为计算机只能识别0和1&#xff0c;无法直接识别文字&#xff0c;那我们是如何在电脑上看到文字的呢&#xff1f; 计算机按照一…

C++的动态数组vector番外之capacity

今日诗词&#xff1a; 爱他明月好&#xff0c;憔悴也相关。 西风多少恨&#xff0c;吹不散眉弯。 ——《临江仙寒柳》【清】纳兰容若 目录 引言 正文 string中的和vector中的capacity有什么区别 vector扩容时内存分配的策略是什么&#xff1f; capacity在vector中的表现如…

基于无人机边沿相关 ------- IBUS、SBUS协议和PPM信号

文章目录 一、IBUS协议二、SBUS协议三、PPM信号 一、IBUS协议 IBUS&#xff08;Intelligent Bus&#xff09;是一种用于电子设备之间通信的协议&#xff0c;采用串行通信方式&#xff0c;允许多设备通过单一数据线通信&#xff0c;较低延迟&#xff0c;支持多主机和从机结构&a…

redis | Django小项目之Mysql数据库和Redis缓存的应用

Django小项目 需求整体架构图技术细节环境配置各文件配置settings.pyurls.pyviews.pyuser_update.html 结果相关代码补充r.hgetall(cacahe_key)new_data {k.decode():v.decode() for k,v in data.items()} 需求 整体架构图 技术细节 环境配置 django-admin startprojrct rmysi…

WIFI 应用层代码

1.0 定义枚举类型 typedef enum {WIFI_COMM_WAIT, // AT 等待命令WIFI_COMM_OK, // AT 命令完成WIFI_COMM_FALL, // AT 命令失败 }WifiCommState_t; 注&#xff1a;该枚举类型的作用是&#xff0c;定义三个成员变量&#xff0c;分别表示AT指令等待发送&#xff0c;AT指令…

unity游戏开发——(细)深入解析 Unity 地形系统:从基础到高级应用

Unity游戏开发 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发前言深入解析 Unity 地形系统&#xff1a;从基础到高级应用一、初识 Unity 地形系统1. 地形尺寸与分辨率 二、地形编辑工具详解1…

下拉菜单 匹配搜索

操作版本&#xff1a;Excel 2010 下拉菜单 涉及到的函数&#xff1a; INDIRECT函数&#xff1a;返回由文本字符串指定的引用 原文链接 一级下拉菜单 方法一&#xff1a;手动输入 选中要制作下拉菜单的单元格区域&#xff0c;单击【数据】-【数据有效性】-【序列】&#…

15.CentOS7升级内核

升级内核 1.配置镜像源 vim /etc/yum.repos.d/elrepo.repo[elrepo] nameelrepo baseurlhttps://mirrors.aliyun.com/elrepo/archive/kernel/el7/x86_64 gpgcheck0 enabled12.备份 cd /etc/yum.repos.d/ mv local.repo repo.bak/ 3.清缓存 yum clean all 4.升级内核 yum ins…

背部筋膜炎最好的恢复办法

背部筋膜炎是由于寒冷、精神紧张、潮湿或慢性劳损等因素造成的背部肌筋膜和肌组织发生水肿、纤维变性和渗出&#xff0c;其主要症状包括&#xff1a; 1、疼痛&#xff1a;患者通常会出现背部疼痛&#xff0c;这种疼痛在着凉或劳累时可能会加重。晨起时疼痛可能尤为明显&#x…

将两对象(重复属性不替换)合并成一个对象

将这两个对象合并成一个对象 const obj1 {"configType": "all","config": {"a":1} };const obj2 {"target_cluster": "dev-0821","type": "import","config": {"connector…

攻防世界-web题型-4星难度汇总-个人wp

Confusion1 进入页面查看源代码&#xff0c;发现有两个提示 访问第一个源码里面有个 /opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt /opt/salt_b420e8cfb8862548e68459ae1d37a1d5.txt 不过我发现好像是只要访问404页面都有这两个。。。 另外这两个admin和login页面都没用…

如何把照片转换成PDF格式?分享3种好用的PDF转换方法

在数字化的时代中&#xff0c;各种格式的文件已经是我们平时办公中不可或缺的一部分&#xff0c;其中尤其是以图片、PDF这两种文件使用的最多&#xff0c;图片能够更加直观的表现内容&#xff0c;而PDF文档因其稳定性、兼容性等特性&#xff0c;也在办公中有独特的优势&#xf…

Pandas DataFrame的创建方法(Create DataFrame)

pandas是一个第三方数据分析库&#xff0c;其集成了大量的数据模型和分析工具&#xff0c;可以方便的处理和分析各类数据。其中主要对象类型有Series&#xff0c;DataFrame和Index。本文介绍DataFrame对象的基本创建方法。 关于DataFrame的基础用法&#xff0c;可以查看下面的…

随机生成n个字节os.urandom(n)

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 随机生成n个字节 os.urandom(n) [太阳]选择题 下列输出结果中正确的是? import os print("【执行】a os.urandom(2)") a os.urandom(2) print("【显示】a ", a) pri…

【Qt】输入类控件QDail

目录 输入类控件QDail 例子&#xff1a;调整窗口不透明度 输入类控件QDail 使用QDail表示一个旋钮&#xff0c;通过鼠标拖动旋钮可以完成一些相关的属性。 核心属性 属性说明 value 持有的数值. minimum 最⼩值 maximum 最⼤值 singleStep 按下⽅向键的时候改变的步⻓…

【Java数据结构】---二叉树OJ

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 文章目录 相同的树另一颗树的子树翻…

与copilot 结对编程系列 - log日志重复性检测 - 第4篇 - 网页UI界面

背景 细节可以参考这篇文章: 与copilot 结对编程系列 - log日志重复性检测 - 第1篇 - 总体介绍及效果展示 本文主要将数据库中存储的数据通过网页调用并展示出来, 以下是对详细解释。 web框架选择 当前场景使用 Flask 来展示网页信息. 主要原因如下&#xff1a; 轻量级和易…

如何使用JavaScript获取HTML表单中的值?

在开发中&#xff0c;我们经常需要获取用户在表单中输入的数据&#xff0c;然后进行处理或提交到服务器。今天我们就来聊一聊&#xff0c;如何用JavaScript获取HTML表单中的值。 使用 FormData 构造函数 FormData 是一个非常方便的工具&#xff0c;它可以把表单中的所有数据打包…

C++,std::chrono 详解

文章目录 1. 概述2. 时间点&#xff08;Time Points&#xff09;3. 时间间隔&#xff08;Durations&#xff09;4. 时钟&#xff08;Clocks&#xff09;5. 时间算术6. 时间转换7. 延时参考 1. 概述 std::chrono 是 C11 引入的一个库&#xff0c;用于处理日期和时间。它提供了一…