天天看點

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);

//非阻塞方式延時,不會卡住主界面,據說可能有問題

QTime endTime = QTime::currentTime().addMSecs(msec);

while (QTime::currentTime() < endTime) {

QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

#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則沒有這個差別。

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()

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模式。

繼續閱讀