QML高效率Table的实现

TableView超多列的解决办法

问题描述

在QML中我们经常商用TableView来进行数据的展示。大部分情况下使用Qt Quick Controls 1自带的TableView是问题不大的。但在某些情况下则会有力不从心的感觉,比如表格的列可能有一百甚至数百列的时候就会出现刷新效率低下的问题。

查看TableView的源码你会发现这是TableView的实现是以行为基本单位,在行数很多时只会实现真正显示的那十几行的委托。所以在行数过多时问题也不大。

但在Qt Quick Controls 1中的TableView只针对行进行了优化,它实现时没有考虑列数过多的情况。当表格的列有300列时,哪怕只刷新表格显示的20行,也会有将近6000个对象进行绘制。

解决办法

对于这个问题,你可以将Qt Quick Controls 1的TableView源码分离出来,自己针对这一部分进行优化。但这个方法比较费力不讨好,出现新的bug的可能性更大。

索性Qt官方也知道自己的这个问题了,所以在后来增加了一个新的TableView。下面针对这个新的TableView说一下。

前提条件

在Qt 5.12的版本中官方增加了这个他们宣传更加高效快速的TableView。所以如果你的无法升级到Qt 5.12以上的版本,这篇文章对你意义不大可以右上角了。

新TableView的引用

众所周知Qt Quick Controls 1有很多问题,Qt官方处于种种原因又重复造了一次轮子这就是Qt Quick Controls 2。而这里介绍到的TableView也是Qt官方在5.12版本又造的一次轮子。所以在QML项目中如果不注意应用很容易混淆这两个控件。

  • 使用之前的TableView一般是引用以下插件
import QtQuick.Controls 1.4

在Qt creator中是这些属性
在这里插入图片描述

  • 而新版本的TableVew是来自以下插件
import QtQuick 2.12

在Qt creator中是这些属性
在这里插入图片描述

新TableView的效果

Qt官方给出了两个TableView的效果,其实我更愿意称之为Excel,其用法和我们想要的TableView效果差距还是很大的。
在这里插入图片描述
看到这个图大伙可能知道我为什么这么说了。因为这个Table没有表头没有列名……

新TableView的问题

新TableView是以单元格为基本单位进行绘制,也就是说它只会绘制你表格显示在界面中的数据。即时你有3000列x1000行,它也只会绘制你界面实际显示的6x20行。绘制对象少了不止一个量级。

所以在效率上确实不需要担心。本人实测300列插入10000行的时间也不到1ms。

  • 但有利有弊,以单元格作为基本单位进行选择绘制的第一个问题就是新TableView没有行的概念!
    在这里插入图片描述
    这句话的意思不是没有行数这个属性了,在新TableView中还是有rows这个参数的,我说没有行是指不存在类型之前TableView的rowDelegate这种用法。

  • 第二个问题就是新TableView不自带表头
    所以得自己去处理列名、表头绘制……

  • 第三个问题就是无法再通过role属性直接访问表格的值

自定义TableView

如果你看到这里还没有放弃看下去的想法,那看来也是被QML的这个问题逼得够呛。如果你没有更好的解决方案暂且看看我的例子,希望对你有所帮助。

代码我也传一份到CSDN,为了照顾部分没分的同学,我这里贴一些。写的时候部分地方用到了公司的代码所有进行了部分调整,颜色搭配需要下下来后再次调整。

  1. 自定义表头
    新TableView没有表头只有我们自己来手动实现一个,这部分算最简单的。几十行代码也够用了。
    一下是TableHead的代码

TableHeader.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

Item{
   
    id: header_horizontal

    //暂存鼠标拖动的位置
    property int posXTemp: 0
    MouseArea{
   
        anchors.fill: parent
        onPressed: header_horizontal.posXTemp=mouseX;
        onPositionChanged: {
   
            if(table_view.contentX+(header_horizontal.posXTemp-mouseX)>0){
   
                table_view.contentX+=(header_horizontal.posXTemp-mouseX);
            }else{
   
                table_view.contentX=0;
            }
            header_horizontal.posXTemp=mouseX;
        }
    }
    Row {
   
        id: header_horizontal_row
        anchors.fill: parent
        leftPadding: -table_view.contentX
        clip: true

        Repeater {
   
            model: table_view.columns > 0 ? table_view.columns : 0

            Rectangle {
   
                id: header_horizontal_item
                width: table_view.columnWidthProvider(index)+table_view.columnSpacing
                height: parent.height
                color: "red"//自己配色


                border.width: 1
                border.color: "#1a2b3c"


                Label {
   
                    width:parent.width
                    height:control.horHeaderHeight
                    horizontalAlignment: Text.AlignHCenter
                    //anchors.fill: parent
                    text: _sourceModel.headerData(index,Qt.Horizontal)
                }

                Rectangle {
   
                    width: parent.width
                    height: filterMode*25
                    anchors.bottom: parent.bottom
                    color: "blue"
                    visible:height !== 0
                    TextInput{
   
                        anchors.fill: parent
                        onTextChanged:{
   
                          //  console.log(text,index)
                            //设置过滤条件
                            _displayModel.setCondition(index,text)

                            table_view.forceLayout()
                        }
                    }
                    Behavior on height {
   
                        PropertyAnimation{
    duration : 200 }
                    }
                }





                Rectangle{
   
                    width: 1
                    height: parent.height
                    anchors.right: parent.right
                    color: "black"
                    opacity: 0.5
                }
                MouseArea{
   
                    width: 3
                    height: parent.height
                    anchors.right: parent.right
                    cursorShape: Qt.SplitHCursor
                    onPressed: header_horizontal.posXTemp=mouseX;
                    onPositionChanged: {
   
                        if((header_horizontal_item.width-(header_horizontal.posXTemp-mouseX))>10){
   
                            header_horizontal_item.width-=(header_horizontal.posXTemp-mouseX);
                        }else{
   
                            header_horizontal_item.width=10;
                        }
                        header_horizontal.posXTemp=mouseX;

                        //改变某列的宽度
                        control._columnWidthArr[index]=(header_horizontal_item.width-table_view.columnSpacing);
                        //刷新布局,这样宽度才会改变
                        table_view.forceLayout();
                    }
                }
            }
        }
    }
}

TableScrollBar.qml


import QtQuick 2.12
import QtQuick.Controls 2.5

ScrollBar {
   
    id:scroRoot
  //  policy: ScrollBar.AlwaysOn
    contentItem: Rectangle{
   
        visible: (scroRoot.size<1.0)
        color: scrollBarColor
    }
}

TableCell.qml

import QtQuick 2.12

import QtQuick.Controls 1
  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值