liudianwu 发表于 2022-3-8 08:43:55

Qt开发经验小技巧196-200

196. 关于Qt延时的几种方法。
```cpp
void QUIHelperCore::sleep(int msec)
{
    if (msec <= 0) {
      return;
    }


#if 1
    //非阻塞方式延时,现在很多人推荐的方法
    QEventLoop loop;
    QTimer::singleShot(msec, &loop, SLOT(quit()));
    loop.exec();
#else
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
    //阻塞方式延时,如果在主线程会卡住主界面
    QThread::msleep(msec);
#else
    //非阻塞方式延时,不会卡住主界面,据说可能有问题
    QTime endTime = QTime::currentTime().addMSecs(msec);
    while (QTime::currentTime() < endTime) {
      QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    }
#endif
#endif
}
```


197. 随着国产化的兴起,各种国产系统和国产数据库等逐渐进入开发者的世界,罗列几个要点。
- 中标麒麟neokylin基于centos。
- 银河麒麟kylin早期版本比如V2基于freebsd,新版本V4、V10基于ubuntu。
- 优麒麟ubuntukylin就是ubuntu的汉化版本,加了点农历控件啥的。
- deepin基于debian。
- uos基于deepin或者说是deepin的商业分支。
- ubuntu基于debian。
- linux界主要分两种发行版本,debian(ubuntu、deepin、uos、银河麒麟kylin等)和redhat(fedora、centos、中标麒麟neokylin、中兴新支点newstart等),分别对应apt-get和yum安装命令。绝大部分的linux系统都基于或者衍生自这两种发行版本。
- 理论上基于同一种系统内核的,在其上编译的程序可以换到另外的系统运行,前提是编译器版本一致,比如都是gcc4.9,在ubuntu14.04 64位用gcc4.9编译的Qt程序,是能够在uos 64位上运行的。
- 高版本编译器的系统一般能够兼容低版本的,比如你用gcc4.9编译的程序是能够在gcc7.0上运行,反过来不行。
- 意味着如果你想尽可能兼容更多的系统,尽量用低版本的编译器编译你的程序,当然要你的程序代码语法支持,比如c++11就要从gcc4.7开始才支持,如果你的代码用了c++11则必须至少选择gcc4.7版本及以上。
- 用Qt编写linux程序为了发布后的可执行文件可以兼容各种linux系统,只要在这两种内核(debian、redhat)的系统上用低版本的编译器比如gcc4.7编译qt程序发布即可。
- 2022-01-27补充:根据Qt官方安装包,发现基于redhat的gcc4.9编译器发布的,通用各种linux系统(亲测ubuntu各个版本、fedora、centos、deepin、uos、银河麒麟kylin、中标麒麟neokylin、中兴新支点newstart等),自己按照这个版本也亲测打包发布了亲测可用,我擦,redhat系统的也可以在debian系统跑。
- 2022-02-10补充:debian上静态编译的程序也可以在redhat系统跑,可能静态编译去掉了很多依赖吧。
- 2022-03-01补充:低调大佬补充,如果没有特定的依赖关系,高版本的编译器编译的程序也可以在低版本编译器的系统运行,比如alpine Linux下用gcc11/clang13编译生成的可执行二进制,依然可以在cenos5/ubuntu10上运行。并不是编译器版本的问题,也不是C++11特性的问题,这个问题涉及到太多,内核版本、gnu libc、ABI兼容等等,两句话说不清。
- 按照QtCreator软件采用的编译器环境规则,一般来说就是低版本的可以在高版本运行,比如Qt5可以在ubuntu14/16/18/20运行,但是高版本编译器编译的就无法在低版本编译器系统运行,会提示缺少GLBC、LIBCXX、symbol xxxxxx等,比如Qt6可以在ubuntu20运行而无法在ubuntu18/16/14等运行。
- 在uos上做开发,建议采用系统自带的Qt库环境开发,以及命令行安装开发环境,不建议使用Qt官方的安装包搭建环境,因为uos的Qt是魔改过的,用Qt官方的标准安装包的环境开发出来的程序,打包发布很可能会有依赖问题而无法运行,而用系统自带的就不存在这个问题。
- 国产人大金仓数据库用的是postgresql数据库改的,意味着你在Qt中用postgresql数据库插件也是能够连接到人大金仓数据库的。
- 以上未必完全正确,欢迎各位指正。


198. 纵观Qt的发展历史,也几乎经历着合久必分、分久必合的逻辑,比如最开始QPushButton等UI控件类都是在QtGui模块中,后面越发臃肿不方便管理和升级迭代,又分离出一个QtWidgets模块;到Qt6又将QList和QVector合并了成了一个类,搞得像分久必合;而且一些数学函数以及封装的c++标准函数库的方法,逐渐放弃了Qt自己的封装改用c++标准函数库,从开始的分到现在的合统一。


199. Qt一直在持续升级迭代,尽管新增加的代码质量明显不如诺基亚时代,但最起码有行动,慢慢完善。目前主要的升级改善在qml模块,底层也有完善,毕竟无论是widget还是qml都是公用一套底层逻辑类,底层基础一定要扎实稳固,个人这几年一直对比测试过不同Qt版本(从旧版本到新版本)很多类和函数的性能,发现官网列出来的新版本对应类和方法的性能提升改善,确实没有说谎,至于提升了多少这块有没有吹牛逼那就不清楚。
- base64算法性能提升很大。
- QStringList等凡是使用了QList相关的类,性能提升巨大。
- 对比测试大概从5.12版本开始QStringList和QMap性能相当。
- 早期版本QStringList如果查找的值先插入则时间越短,QMap则没有这个区别。
```cpp
QStringList list1, list2;
QMap<QString, QString> map;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    for (int i = 0; i < 100000; ++i) {
      QString s1 = QString("%1").arg(i);
      QString s2 = QString("A%1").arg(i);
      list1 << s1;
      list2 << s2;
      map.insert(s1, s2);
    }
}


void MainWindow::on_pushButton_clicked()
{
    QElapsedTimer time;
    time.start();
    qDebug() << "111" << time.nsecsElapsed() << list2.at(list1.indexOf("9999"));
}


void MainWindow::on_pushButton_2_clicked()
{
    QElapsedTimer time;
    time.start();
    qDebug() << "222" << time.nsecsElapsed() << map.value("9999");
}
```


200. 关于QtCreator中三种不同编译版本 debug、release、profile 的区别。
- debug调试模式,编译后的可执行文件很大,带了很多调试符号信息等,方便开发阶段调试的时候进入具体的堆栈查看值。会打开所有的断言,运行阶段性能差速度慢,可能会有卡顿感觉。
- release发布模式,编译后的可执行文件很小,不带任何调试符号信息,一般用于打包发布程序。由于经过了各种优化,会关闭所有断言,运行阶段性能最好,如果有卡顿那肯定是你的程序问题。
- profile概述模式,编译后的可执行文件比debug小很多比release大一点,带有部分调试符号信息,在debug和release之间取一个平衡,兼顾性能和调试,性能更优但是又方便调试。
- 使用Qt5.7版本对应三种模式编译的空白窗体程序大小:debug(1319kb)、release(24kb)、profile(90kb)。
- debug链接的库是带d结尾的,release和profile链接的库是不带d结尾的,很多人以为profile链接的是带d结尾的其实是错误的。
- 新的Qt在线安装程序在安装的时候,可以勾选是否安装debug调试库(对应lib目录下一堆带d结尾的文件),以前的版本是默认都安装,现在可选安装以便减少体积。
- 无论是否安装了debug调试库,你都可以选择debug模式生成对应debug的文件,这个不知道怎么做到的。
- 无论是哪种模式,都可以在程序中开启日志钩子输出日志信息,方便收集运行阶段的各种信息反馈给开发人员查看问题。
- 最初的开发工具一般是具有debug和release两种模式,随着用户需求的增加和场景的需要,部分开发工具衍生出了profile模式,更有甚者比如flutter还有第四种test模式。

页: [1]
查看完整版本: Qt开发经验小技巧196-200