第十三章 MDXUI最佳实现(6)

上一章我们了解了CDxMainWindow的使用以及实现了一个日志显示的文本框,这一章我们介绍一些复杂的控件,CDxTabWindow,CDxTabWidget,CDxTableWindow,CDxTableWidget,嗯,为什么这些会有两个版本呢?包括CDxListWindow也有一个CDxListWidget版本,这个要从很早之前说起,设计之初其实都只有一个版本,因为当时只考虑到数据,并没有考虑到在这些空间中放置组件这种东西,所以一开始只设计了Window版本,该版本使用的是数据驱动视图模型,所以在效率上是非常高的,比如CDxTableWindow,这是一个表格控件,对于成千上万个单元数据,用它来显示最好不过了,如果使用CDxTableWidget来显示这么多单元数据,效率就非常糟糕,但是如果我们想在单元格子里面放置一些Button控件什么的,CDxTableWindow就没法做到了,而CDxTableWidget就非常适合。

对于编程来说,千言万语不如代码两行,所以说了这么多,不如我们来看看代码以及展示出来的效果。

CDxTabWidget是一个页面控件,我们可以尝试添加一些东西,看看具体效果,CDxTableWindow用来展示数据,CDxTableWidget用来展示控件,所以我们可以添加一些数据和添加一些控件。对于CDxTableWindow来说添加数据非常简单,我们可以从文件中读取数据,然后设计进去即可。

由于CDxTableWidget是用来放置控件的,所以使用起来相对就稍微难一些了,因为我们首先要创建这些控件,再设置上去才可以,我们可以使用一个小函数来创建这些控件:

CDxFlatButtonEx 设计之初就是专用来设置给CDxTableWidget的,它被设计为长宽随着表格的变化而变化,有了这个小函数后我们就可以轻松的填充CDxTableWidget啦。

运行程序,我们看到不同的效果,这就是CDxTableWindow和CDxTableWidget的区别。

这里我们用到两个数据类型,mj::dmat和TL::MSNoSqlDB,不用在意TL::smat,TL::smat和mj::dmat是一个类型,我们现在来看看这个类型:

MMatrixSheet 是一个矩阵的模板类,如下:

关于这个矩阵的具体实现这里不细说,大家感兴趣的话可以去GitHub上下载,在MToolLib下面的MMatrixSheet.h文件中,该矩阵的特殊之处是可以为每个单元格设置一个属性。如果大家细心的话会发现整个DxUI框架提供了很多对数据处理的东西,MMatrixSheet是用于处理矩阵,MTLSheet用于处理一般的数据,TL::Vector用于处理列表数据,MNoSqlDB模拟数据库的一个模板库,在DxConfig.h中就专门提供了一些数据处理方法,比如快速傅里叶变换,卷积等操作:

所以我们这个DxUI提供了大量的数据处理工具,除了这些方便的工具外还有一个重量级的数据处理工具——MNoSqlDB,顾名思义,这就是为模拟数据库的工具,不需要SQL语句可以实现对数据删增查找等数据库常用操作。

MNoSqlDB 可以直接从文件中读取数据,当然读取数据这种小事没啥了不起,但是能够读取指定类型这种事就厉害啦:

这个代码是从Enquipment.txt读取数据,每个数据之间使用制表符分割,然后将每段数据转换成指定的类型,比如第一段数据转换成bool,其余的转换成MString,下面是文件的内容:

在MNoSqlDB读取数据时可以选择过滤掉不需要的信息,这里带#号的行都是不读取的,嗯,这个操作非常有技巧性,目前看来也就我使用这个技巧啦,至少还没遇到有人这么干过,所以这里展示一下这个过程,这个技巧以前在CSDN上面发过,好像在前面的章节中有说过吧,不管了,既然这里又说回来,那就展示一下,否则再回去查找这个东西也不容易。

在MNoSqlDB内部使用vector来管理数据数据,使用MMultType来存放数据,关键在于MMultType,其实这个MMultType如果简单来说可以使用std::tuple来替换,但是std::tuple的实现有一个缺陷,当然这可能是标准库定义之时有意这么安排的,那就是我们没法获取std::tuple里面元素的引用,std::get(tuple)只能获取一个值的拷贝,很多时候我们可能需要获取tuple元素里面的引用,所以MMultType应运而生。

这里的关键和MTypeList有关,MTypeList用于类型计算,MMultType运用MTypeList来存放指定类型的值,下面是MTypeList的实现,代码很简单,但是能够想到写出这几句代码来却又不简单,因为这些看似简单的代码实则已经远远超出一个常规使用C++的范畴,MTypeList是完完整整的元编程,MMultType确实又走在元编程和常规编程之间,这在实现技巧上又增进难度,当然代码不多,还是那句话,能够想到写出这几句代码却又不简单。

结合MTypeList我们可以实现出MMultType,下面是MMultType的完整代码:

对于使用MMultType就很简单了,可以像使用std::tuple一样使用:

和std::tuple不同之处在于我们能够获取数据的引用。由于我们对标准库的get进行了特化处理,所以我们也可以使用std::get来获取数据的引用。

说了这么多,我们回到主题,怎么将字符串转换为指定的类型,当然将字符串转换成指定的类型不难,难就难在转换到多个类型任意类型。

首先我们将字符串先按照指定的分隔符进行分割,然后放到一个容器之中,可以根据类型数的大小和容器的大小做判断,如何容器的大小大于等于类型数,作转换,否则不转换,这个操作如下:

我们这里为什么要转换成MString呢?因为MString有提供对模板的支持,MString::ToOtherType可以将字符串转换为其他类型,所以这符合我们的预期。

那么到了这一步,我们要如今进行多类型转换呢?常规的方法行不通,因为这属于类型操作,所以我们只能回到元编程的路上,我们可以写一个元函数来实现这个功能。

这个过程其实不难,还是上面那句话,难就难在是否能够想得通,当然更难的是是否能够想得明白我们最后的那个throw,为什么会是throw,因为在递归之后我们已经无法返回我们需要的类型啦,那么该怎么办呢?还有什么地方能够得到我们想要的类型呢?那就是开始递归的地方,所以我们可以在哪里catch我们想要的类型,这就是异常的妙用。我们再回头看看FromStr

我们再来看看MNoSqlDB的loadAll实现。

现在回到我们的CDxTabWidget部分,如果我们将CDxTabWidget换成CDxTabWindow会是什么效果呢?

通过对比两个的外观有点差点,其次是CDxTabWindow的Tab头可以鼠标拉动,可以摆放在四边的任一边,但是高度不可设,而CDxTabWidget的Tab头的高度可设,但不可能挪动位置。

这一章就介绍到这里吧。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181027G0WHHZ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券