QML TableView 实例演示 + 可能遇到的一些问题(Qt_6_5_3)

news2024/11/28 2:30:06

一、可能遇到的一些问题

Q1:如何禁用拖动?

在TableView下加一句代码即可:

interactive: false

补充:这个属性并不专属于TableView,而是一个通用属性。很多Controls下的控件都可以使用,其主要作用就是控制交互的。

举个例子:像width、height、color这些都属于通用属性,并不是说只有一个控件需要指定它的宽高、颜色。这种通用特性在QML是非常常见的。

或许你想给某个控件实现某种功能,没准这个功能其实就是其他控件中的一个属性罢了。

Q2:设置了标题栏之后,程序直接卡死?

可能是Layout布局的问题,把Layout布局换成Item试试。

Q3:表头数据和内容数据重叠显示了?或者一片空白?

大概率还是布局的问题,检查一下吧!

补充:在 HorizontalHeaderView 中使用了 syncView 属性,就相当于是将 HorizontalHeaderView 和指定的 TableView 绑定了,它默认会有个布局,就是把水平标题栏放在表格内容的上方,但是左右的对齐方式可能并不是我们想要的,所以在做整体布局时需要注意这一点。

Q4:不想让用户编辑输入框?

将TextField设为只读就可以啦!

readOnly: true

还有其它问题?

上面的几个问题是我在做这个实例的时候遇到的,如果你有别的问题可以在评论区留言,我会逐一回复哦~

二、QML TableView 实例演示

下面截图中的红框部分就是最终的效果,虽然看似简陋,实际确实有点简陋。。。。

好消息是,这个只是我用来演示给大家看的,并不是我个人审美就这样。。。。所以,等大家学会了怎么去用 TableView 这个控件,就按照自己的想法和需求去设计它吧!

实现步骤1:TableModel

在QML中,像TableView、ListView这种控件,视图(View)和数据(model)都是分开的。所以我们需要依次去完善他们。

那么,先来实现一个model吧!

    //表头数据放TableModelColumn里,内容数据放rows里,由TableModel统一管理
    TableModel
    {
        id: tablemodel_2
        TableModelColumn { display: "状态" }  //后面表头会用到
        TableModelColumn { display: "简称" }
        TableModelColumn { display: "售价" }
        TableModelColumn { display: "库存" }

        rows:   //表格里具体显示的内容
                [
            {
                "状态": true,
                "简称": "AK-74自动步枪",
                "售价": 149,
                "库存": 500
            },

            {
                "状态": true,
                "简称": "81式自动步枪",
                "售价": 199,
                "库存": 300
            },

            {
                "状态": true,
                "简称": "M16突击步枪",
                "售价": 119,
                "库存": 100
            },

            {
                "状态": true,
                "简称": "SCAR突击步枪",
                "售价": 129,
                "库存": 100
            },

            {
                "状态": true,
                "简称": "HKG36突击步枪",
                "售价": 159,
                "库存": 100
            }
        ]
    }

在上面的代码片段中,最外层是1个TableModel,这个TableModel和TableView是同级的,不是写在TableView下面的哈,文章最后我会把完整的代码也发出来。

我们这个TableModel定义1个id叫tablemodel_2,因为等会后面需要通过id来调用这个TableModel里面的数据。

接着,我们连续写了4行TableModelColumn,这个是后面要用到的水平标题栏的数据,每一个TableModelColumn就代表1列。

最后是1个 rows,这个rows后面紧跟的一个是列表[ ],列表里面放的就是除表头以外的数据了。形式就是花括号里一对对的键和值,而键就是上面TableModelColumn中的文本,也就是列名,值才是每个单元格中具体要显示出来的数据。

然后你可能会想到,哎呀~这么多行代码下去,实际就显示5行数据,如果列很多、数据成千上万,这代码得写多长啊!

这点不用担心啦!因为QML的专家早就考虑到了。如果数据量很少,而且是固定的,model直接写出来就行了。如果数据多,那最好用C++的模型类来提供。需要注意的是:C++模型必须是QAbstractItemModel的子类。

这个C++的模型类有点复杂,后面我会专门写一篇文章来介绍它。

实现步骤2:TableView

做完数据层(model),下面我们就来做具体的外观(View)吧!请看下面代码:

 View层,大概分为2个部分,蓝色框框里是一些整体的属性设置,绿色框框里是针对每一列数据的显示细节的描述。

在delegate中,我们写了4个DelegateChoice。一共是5行数据,为什么我们只写了4个?因为如果你只是简单的显示model里的数据、不会有交互,那么就统一用一个DelegateChoice就行啦!

什么叫不会有交互?你看前面截图中第一列的数据是不是都是复选框?复选框是干嘛的?不就是给用户去勾选、去交互的嘛~

所以像这种后期会交互的数据列,就要单独的DelegateChoice去写。我展开第一个DelegateChoice中的代码给你看一下:

DelegateChoice {
                column: 0   //指定哪一列可编辑

                delegate: Rectangle
                {
                    implicitWidth: 150
                    implicitHeight: 40

                    color: t_tableView_2.currentRow === row ? "#c8e5b3" : "#eeeeee"

                    CheckBox
                    {
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left

                        checked: model.display  //CheckBox的默认状态就是模型里的值
                        onToggled: model.display = checked  //编辑即更新数据到模型

                        Material.accent: "green"
                    }
                }
            }

看到了吗?里面竟然还有一个delegate?这个最里层的delegate就是设置具体的单元格的显示方式啦!

可能有了解ListView的小伙伴好奇了,我之前做ListView的时候只需要1个delegate就行了,怎么这个TableView还要套2层delegate,外面竟然还有个什么DelegateChoice?这个DelegateChoice又是什么?干啥用的?

这个DelegateChoice是按列去设置的,每一列都有不同的情况和需求,如果我们这个表格是涉及到交互、而不单单是给用户看看的,那就需要用DelegateChoice对具体的列去设置,因为可能第1列全部是复选框,第3列又全都是单行输入框,怎么都得去单独设置~

实现步骤3:HorizontalHeaderView

这个HorizontalHeaderView就是水平标题栏啦!

HorizontalHeaderView {
        id: horizontalHeaderView

        syncView: t_tableView_2

        interactive: false  //禁用拖动

        delegate: Rectangle {
            implicitWidth: 150; implicitHeight: 40; color: "transparent"

            Text {
                text: tablemodel_2.columns[index].display
                font.bold: true

                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
            }
        }
    }

这个水平标题栏和TableView也是同级的,不要写到TableView里面去喽!

在QML中,标题栏和表格是分开设置的,所以设置了标题栏之后需要通过syncView属性去绑定具体的TableView。

然后这个水平标题栏也是默认有交互效果的,如果你不想让它动,就也用interactive属性禁用吧!

实现步骤4:降序、升序

排序功能就是对model中的数据进行冒泡排序,如果默认是降序,那么对降序取反就是升序啦!

冒泡排序是写在了MouseArea中的onClicked信号下,细心的小伙伴会发现,这个MouseArea覆盖的是Text,而不是Rectangle。

这是因为,如果直接覆盖Rectangle,那么HorizontalHeaderView自带的列宽调整功能就失效啦!

    HorizontalHeaderView {
        id: horizontalHeaderView

        syncView: t_tableView_2

        interactive: false            //禁用拖动

        property bool isDesc: true    //默认表格内的数据是降序排列

        delegate: Rectangle {
            implicitWidth: 150; implicitHeight: 40; color: "transparent"

            Text {
                text: tablemodel_2.columns[index].display + " " + ( horizontalHeaderView.isDesc ? "∨" : "∧" )   //添加排序标识符号
                font.bold: true
                font.family: "Microsoft YaHei"

                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10

                MouseArea {
                    anchors.fill: parent    //排序生效区域覆盖文字区域而不是整个矩形,否则表头的列宽调整功能将失效

                    onClicked: {
                        var headerKey = tablemodel_2.columns[index].display

                        for ( var i = tablemodel_2.rowCount -1; i > 0; i-- ) {
                            for ( var j = 0; j < i; j++ ) {
                                if ( horizontalHeaderView.isDesc ) {
                                    if ( tablemodel_2.getRow(j)[headerKey] > tablemodel_2.getRow(j + 1)[headerKey]) {
                                        tablemodel_2.moveRow(j, j + 1, 1)
                                    }
                                }

                                else {
                                    if ( tablemodel_2.getRow(j)[headerKey] < tablemodel_2.getRow(j + 1)[headerKey] ) {
                                        tablemodel_2.moveRow(j, j + 1, 1)
                                    }
                                }
                            }
                        }

                        horizontalHeaderView.isDesc = !horizontalHeaderView.isDesc
                    }
                }
            }
        }
    }

完整代码

import QtQuick
import QtQuick.Controls.Material
import QtQuick.Controls
import QtQuick.Layouts
import Qt.labs.qmlmodels    //TableModel需要用到的库

Item {

    //表头数据放TableModelColumn里,内容数据放rows里,由TableModel统一管理
    TableModel
    {
        id: tablemodel_2
        TableModelColumn { display: "状态" }  //后面表头会用到
        TableModelColumn { display: "简称" }
        TableModelColumn { display: "售价" }
        TableModelColumn { display: "库存" }

        rows:   //表格里具体显示的内容
                [
            {
                "状态": true,
                "简称": "AK-74自动步枪",
                "售价": 149,
                "库存": 500
            },

            {
                "状态": true,
                "简称": "81式自动步枪",
                "售价": 199,
                "库存": 300
            },

            {
                "状态": true,
                "简称": "M16突击步枪",
                "售价": 119,
                "库存": 100
            },

            {
                "状态": true,
                "简称": "SCAR突击步枪",
                "售价": 129,
                "库存": 100
            },

            {
                "状态": true,
                "简称": "HKG36突击步枪",
                "售价": 159,
                "库存": 100
            }
        ]
    }

    TableView
    {
        id: t_tableView_2

        width: contentWidth
        height: contentHeight

        anchors.top: horizontalHeaderView.bottom

        interactive: false  //禁止拖动
        rowSpacing: 1       //行间距。列间距是columnSpacing

        model: tablemodel_2

        //行选择,选中事件的处理
        selectionModel: ItemSelectionModel {}

        //指定可编辑的列,把CheckBox控件放进表格中
        delegate: DelegateChooser {
            DelegateChoice {
                column: 0   //指定哪一列可编辑

                delegate: Rectangle
                {
                    implicitWidth: 150
                    implicitHeight: 40

                    color: t_tableView_2.currentRow === row ? "#c8e5b3" : "#eeeeee"

                    CheckBox
                    {
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left

                        checked: model.display  //CheckBox的默认状态就是模型里的值
                        onToggled: model.display = checked  //编辑即更新数据到模型

                        Material.accent: "green"
                    }
                }
            }

            DelegateChoice {
                column: 2

                delegate: Rectangle
                {
                    implicitWidth: 150
                    implicitHeight: 40

                    color: t_tableView_2.currentRow === row ? "#c8e5b3" : "#eeeeee"

                    BasicTextField
                    {
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left
                        anchors.leftMargin: 10

                        width: 80; height: 30

                        text: model.display

                        onAccepted: model.display = text            //回车更新数据
                        onEditingFinished: model.display = text     //焦点改变更新数据
                    }
                }
            }

            DelegateChoice {
                column: 3

                delegate: Rectangle
                {
                    implicitWidth: 150; implicitHeight: 40
                    color: t_tableView_2.currentRow === row ? "#c8e5b3" : "#eeeeee"

                    BasicTextField
                    {
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left
                        anchors.leftMargin: 10

                        width: 80; height: 30

                        text: model.display

                        onAccepted: model.display = text            //回车更新数据
                        onEditingFinished: model.display = text     //焦点改变更新数据
                    }
                }
            }

            DelegateChoice   //默认显示方式,不指定具体列
            {
                delegate: Rectangle
                {
                    implicitWidth: 150; implicitHeight: 40

                    //选中行变色(生效前提是:为selectionModel分配一个ItemSelectionModel)
                    color: t_tableView_2.currentRow === row ? "#c8e5b3" : "#eeeeee"

                    Text
                    {
                        text: display

                        anchors.verticalCenter: parent.verticalCenter
                        anchors.left: parent.left
                        anchors.leftMargin: 10
                    }
                }
            }
        }
    }

    HorizontalHeaderView {
        id: horizontalHeaderView

        syncView: t_tableView_2

        interactive: false  //禁用拖动

        delegate: Rectangle {
            implicitWidth: 150; implicitHeight: 40; color: "transparent"

            Text {
                text: tablemodel_2.columns[index].display
                font.bold: true

                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
            }
        }
    }
}

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

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

相关文章

详细描述一下Elasticsearch更新和删除文档的过程?

大家好&#xff0c;我是锋哥。今天分享关于【详细描述一下Elasticsearch更新和删除文档的过程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 详细描述一下Elasticsearch更新和删除文档的过程&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 E…

(五)Ubuntu22.04+Stable-Diffusion-webui AI绘画 模型转换插件安装及其使用

一、说明 这是秋叶大佬开发的一个模型转换插件&#xff0c;秋叶整合包中自带。如果你的 Stable Diffusion WebUI 中没有这个插件&#xff0c;请使用下面这个地址安装&#xff0c;安装完成之后别忘了重启 WebUI。 模型转换插件 https://github.com/Akegarasu/sd-webui-model-c…

Python数据分析实例五、US 大选捐款数据分析

美国联邦选举委员会 (FEC) 公布了对政治竞选活动的贡献数据。这包括投稿人姓名、职业和雇主、地址和投款金额。2012 年美国总统大选的贡献数据以单个 150 MB 的 CSV 文件P00000001-ALL.csv形式提供,该文件可以通过以下pandas.read_csv加载: import pandas as pdfec = pd.r…

原生微信小程序画表格

wxml部分&#xff1a; <view class"table__scroll__view"><view class"table__header"><view class"table__header__item" wx:for"{{TableHeadtitle}}" wx:key"index">{{item.title}}</view></…

TCP/IP协议攻击与防范

一、TCP/IP协议攻击介绍 1.1 Internet的结构​ LAN&#xff1a;局域网 WAN&#xff1a;广域网 WLAN&#xff1a;无线局域网 私有IP地址与公有IP地址&#xff1f; 私有地址&#xff1a;A类&#xff1a;10.0.0.0~10.255.255.255 B类&#xff1a;172.16.0.0~172.31.255.255…

微信小程序2-地图显示和地图标记

一、index修改页面&#xff0c;让页面能够显示地图和一个添加标记的按钮。 index.wxml <scroll-view class"scrollarea" scroll-y type"list"><view class"index_container"><map id"map" style"width: 100%; h…

【C++】从C语言到C++学习指南

如果你也是从C语言一路过来的&#xff0c;那么请一起看下去吧&#xff01; 文章目录 面型对象程序设计C基础C和C一些语法区别C在非对象方面对C语言的扩充C的一些标准&#xff08;兼容旧标准&#xff09; 首先&#xff0c;在C的学习中&#xff0c;我们要时刻清醒一点&#xff1…

Fakelocation Server服务器/专业版 ubuntu

前言:需要Ubuntu系统 Fakelocation开源文件系统需求 Ubuntu | Fakelocation | 任务一 任务一 更新Ubuntu&#xff08;安装下载不再赘述&#xff09; sudo -i # 提权 sudo apt update # 更新软件包列表 sudo apt upgrade # 升级已安装的软…

探索Python的HTTP之旅:揭秘Requests库的神秘面纱

文章目录 **探索Python的HTTP之旅&#xff1a;揭秘Requests库的神秘面纱**第一部分&#xff1a;背景介绍第二部分&#xff1a;Requests库是什么&#xff1f;第三部分&#xff1a;如何安装Requests库&#xff1f;第四部分&#xff1a;Requests库的五个简单函数使用方法第五部分&…

WPF——ICON按钮制作

前言 首先ICON按钮&#xff0c;即带图标按钮&#xff0c;即图标按钮。 图标按钮在开发时&#xff0c;主要是有两种方式来进行。一是在Button的Content内添加Image&#xff0c;然后设置Image的属性Source来实现&#xff0c;这种方式主要是简单易操作&#xff0c;对于初学者来说…

【MySQL篇】持久化和非持久化统计信息的深度剖析(第一篇,总共六篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

三开关VUE组件

一、使用效果 <template><QqThreeSwitch v-model"value" /><!-- <SqThreeSwitch v-model"value" :options"[test1, test2, test3]"><template #left-action><div style"display: flex"><IconMoon…

线段树与树状数组 (C++)

线段树&#xff1a;基于分治思想的二叉树&#xff0c;用于维护区间信息&#xff08;区间和&#xff0c;区间最值等&#xff09;&#xff0c;区间修改和区间查询的时间复杂度为logn 叶子节点存储元素本身&#xff0c;非叶子节点存取区间信息 1.节点&#xff1a;是一个结构体&a…

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数 微信公众平台添加配置 微信公众平台 > 开发管理 > 开发设置 > 扫普通链接二维码打开小程序 配置链接规则需要下载校验文档给后端存入服务器中&#xff0c;保存配置的时候会校验一次&#xff0c;确定当前的配…

数据结构(初阶6)---二叉树(遍历——递归的艺术)(详解)

二叉树的遍历与练习 一.二叉树的基本遍历形式1.前序遍历(深度优先遍历)2.中序遍历(深度优先遍历)3.后序遍历(深度优先遍历)4.层序遍历&#xff01;&#xff01;(广度优先遍历) 二.二叉树的leetcode小练习1.判断平衡二叉树1&#xff09;正常解法2&#xff09;优化解法 2.对称二叉…

spring boot2.7集成OpenFeign 3.1.7

1.Feign Feign是一个声明式web服务客户端。它使编写web服务客户端更容易。要使用Feign&#xff0c;请创建一个接口并对其进行注释。它具有可插入注释支持&#xff0c;包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持&…

基于Redis内核的热key统计实现方案|得物技术

一、Redis热key介绍 Redis热key问题是指单位时间内&#xff0c;某个特定key的访问量特别高&#xff0c;占用大量的CPU资源&#xff0c;影响其他请求并导致整体性能降低。而且&#xff0c;如果访问热key的命令是时间复杂度较高的命令&#xff0c;会使得CPU消耗变得更加严重&…

CTF-Hub SQL 报错注入(纯手动注入)

​ 当输入1时&#xff0c;发现只有查询正确&#xff0c;基本上可以判断出没有回显 开始注入(工具hackerBar) 题目是报错注入&#xff0c;方向就比较明显&#xff0c;大致说一下用到的函数和原理。 常见报错注入函数&#xff1a; 通过 floor() 报错注入通过 extractValue() …

Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch中的节点&#xff08;比如共20个&#xff09;&#xff0c;其中的10个选了一个master&#xff0c;另外10个选了另一个master&#xff0c;怎么办&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch中的节…

linux安装mysql8.0.40

一、下载MySQL安装包 1.查看glibc版本 rpm -qa | grep glibc 2.到mysql官网下载安装包 ​ 二、解压安装 1.上传压缩包纸/usr/local 目录下&#xff0c;解压&#xff1a; tar -xvf mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz 2.重命名&#xff1a; mv mysql-8.0.40-linux-…