Qt总结笔记

1   Qt语法

Qt信号与槽使用方法最完整总结

2   Qt学习资料

3   Qt程序发布的流程

  1. Qt Creator开发程序
  2. 选择release编译后,在源码文件夹之外会生成构建的文件夹,带有-Release尾缀,在这个目录下拷贝程序的exe二进制文件到一个新建的文件夹中。
  3. 运行windeployqt工具打包动态链接文件:windeployqt program_name.exe。确保提前添加环境变量PATH:C:\Qt\qt6release\bin,否则找不到windeployqt程序。P.S. 使用vs cl终端运行windeployqt会同时拷贝vc_redist.x64.exe安装包(Microsoft Visual C++ 2015-2022 Redistributable (x64) - 14.36.32532,可以解决目标系统缺少dll动态链接库的报错),使用普通的终端运行windeployqt则不会拷贝这个文件(Warning: Cannot find Visual Studio installation directory, VCINSTALLDIR is not set.),但实际上可以手动拷贝dll动态链接库文件到程序根目录,可免去用户再次运行安装运行库。
  4. NSIS打包生成安装包:创建快捷方式、创建卸载程序、界面美化(模仿网易云音乐安装包)、判断是否正在运行、判断并安装VC运行库。

3.1   单文件封包流程

除了静态编译可以单文件的打包,动态链接编译开发也可以实现,这个需要使用三方封包工具了,一般都是使用Enigma Virtual Box进行单文件的打包。

单文件打包流程:

  1. 新建文件夹,拷贝qt程序exe,运行windeployqt.exe打包动态链接文件,拷贝额外的MS VC++ DLL文件
  2. 打开Enigma Virtual Box,选择打包的程序
  3. 选择好打包程序后会自动生成一个打包后的程序名
  4. 在增加文件选项里面选择 增加文件夹[递归] ,把前面创建存放文件的文件夹包含进去
  5. 在文件选项 选择压缩文件
  6. 执行封包

缺点:使用Enigma Virtual Box打包的单文件,有可能会被杀毒软件识别为病毒,比如Windows Defender。

4   Qt Creator的总结

4.1   下载

断网再打开Qt Creator的安装包,等跳过检测联网帐号的界面后就可以启用网络继续安装。

4.2   修改模板文件以便新建工程时默认支持C++20

使用程序完成批量修改:modify_qt_creator_template_files_to_support_c++20.bat

将以下文件中的set(CMAKE_CXX_STANDARD 17)修改为set(CMAKE_CXX_STANDARD 20)

  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\consoleapp\CMakeLists.txt
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\cpplibrary\CMakeLists.txt
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\plaincpp\CMakeLists.txt
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\qtquickapplication_compat\CMakeLists.txt
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\qtwidgetsapplication\CMakeLists.txt

将以下文件中的CONFIG += c++17修改为CONFIG += c++20

  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\consoleapp\file.pro
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\cpplibrary\project.pro
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\plaincpp\file.pro
  • qtcreator-14.0.2\share\qtcreator\templates\wizards\projects\qtwidgetsapplication\project.pro

5   Qt国际化多语言的总结

QT官方多语言编程wiki参考:How to create a multi language application

  1. 创建工程文件时,勾选国际化选项。
  2. 打开CMakeLists.txt文件,修改${TS_FILES}对应的文件和手动生成需要的ts文件,找到if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)语句,在该if语句内添加如下内容,其中untitled为项目名称。如果还需要创建对应资源文件的话,就创建languages.qrc并有qt资源编辑器打开编辑。
    1
    2
    3
    4
    5
    6
    7
    qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
    qt_add_executable(untitled
    MANUAL_FINALIZATION
    ${PROJECT_SOURCES}
    ${TS_FILES}
    ${QM_FILES}
    )
  3. 编辑ui文件,编辑程序界面文本。
  4. 构建工程,ts文件会自动生成对应的文本(无需使用QT Creator的工具->外部->Linguist->Update/Release Translations(lupate),这个工具运行会报错)

5.1   创建工程提示找不到合适的套件

问题:安装Qt Creator之后,在创建工程提示No suitable kits found.

解决:点击管理,手动设置构建套件kit的qt版本,这是通过选择qmake.exe或者qmake6.exe的路径确认。(不用重装,网上的教程都是重装或者安装在线版本包,但直接重装是无效)。

5.2   旧项目的套件配置文件中的CL编译器路径不正确

原因:更新MSVC CL后,老版本编译器就被删除了,旧项目的套件配置文件中的CL编译器路径仍然是老版本的路径,导致路径错误无法识别最新版本的编译器。

解决方法:删除项目父路径中生成的构建配置文件夹,例如build-untitled-x64-Release,然后重新构建新的配置文件夹。

6   Qt源码编译

6.1   下载

  • CMake
  • Ninja
  • MSVC CL编译器(Visual Studio 2022 生成工具)
  • Qt源码,以下是我个人使用到的模块(按编译顺序列出)
    • qtbase(基础库)
    • qtshadertools(编译qtdeclarative所需的依赖库)
    • qtdeclarative(qt quick和QML)
    • qttools(CMakeLists文件中指明要Qt Linguist包,因此即使在qt creator中没用上「工具」->「外部」->「Linguist」也要编译)
    • qtsvg(FluentUI库所需)
    • qt5compat(FluentUI库所需)
    • qttranslation(如果不编译这个库,运行windeployqt会出现警告:Warning: Translations will not be available due to the following error. Cannot open C:/Qt/qt6release/translations/catalogs.json。但这个错误实际不影响程序的翻译状态,可以不编译)

6.2   环境配置和编译步骤

环境变量:确保系统PATH环境变量含有CMake和Ninja路径。

注意不能使用ninja直接构建源码,会报错:build.ninja not found。构建是使用CMake。

编译步骤:

  1. 将源码解压到分区的根目录下,例如:G:\qtbase-everywhere-src-6.8.0
  2. 在源码文件夹外新建一个文件夹,如qtbasebuild,拷贝该编译脚本进文件夹,打开cmd窗口,执行该脚本(不建议直接双击运行编译脚本,因为脚本编译出错或者执行完毕都会关闭窗口,这样无法得知编译详情)。
  3. 编译完成后添加环境变量PATH配置:C:\Qt\qt6release\bin

6.3   单模块逐个编译的BAT脚本

附加编译子模块的方式:运行Qt安装路径下的/bin/qt-configure-module.bat + 附件模块源码解压路径。

一般普通开发编译release版本即可,debug版本是是编译用来开发调试qt源码的。

6.3.1   编译release版本

6.3.1.1   编译qtbase(release)

1
2
3
4
@chcp 65001>nul
@echo off
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
..\qtbase-everywhere-src-6.8.0\configure.bat -prefix C:\Qt\qt6release -c++std c++20 -release -optimize-size -shared && cmake --build . --parallel && cmake --install .

6.3.1.2   附加编译其他子模块(release)

1
2
3
4
@chcp 65001>nul
@echo off
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
C:\Qt\qt6release\bin\qt-configure-module.bat G:\qtshadertools-everywhere-src-6.8.0 && cmake --build . --parallel && cmake --install .

6.3.2   编译debug版本

6.3.2.1   编译qtbase(debug)

1
2
3
4
@chcp 65001>nul
@echo off
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
..\qtbase-everywhere-src-6.8.0\configure.bat -prefix C:\Qt\qt6debug -c++std c++20 -debug -shared && cmake --build . --parallel && cmake --install .

6.3.2.2   附加编译其他子模块(debug)

1
2
3
4
@chcp 65001>nul
@echo off
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
C:\Qt\qt6debug\bin\qt-configure-module.bat ..\qtshadertools-everywhere-src-6.8.0 && cmake --build . --parallel && cmake --install .

6.4   编译遇到的坑

6.4.1   系统PATH环境变量含有CL路径,但终端手动编译时依旧报错

问题:系统PATH环境变量含有CL路径,直接输入cl可以查询到该命令。但终端手动编译时依旧出错,cmake等操作无法正常运行。

解决方式:需要在MSVC Cl初始化环境的情况下编译。不能使用普通终端运行,虽然系统PATH有添加可识别CL命令,但是CL相关环境变量只能通过vcvarsall.bat设置,例如vcvarsall.bat x64

6.4.2   无法写入源文件更新的清单

报错信息:mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file

解决方法:多线程编译偶尔引起的现象,重新运行编译脚本命令即可。(个人见解:多线程编译引起资源阻塞,导致写入失败)

6.4.3   找不到qtshadertools 'qsb'工具

报错信息:Note: Qt Quick modules not built due to not finding the qtshadertools 'qsb' tool.

解决方法:qtdeclarative模块依赖于qtshadertools模块,需要先编译安装好qtshadertools,之后再编译安装qtdeclarative。

6.4.4   optimize_size选项导致编译中断

报错信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ERROR: Feature "optimize_size": Forcing to "ON" breaks its condition:
NOT QT_FEATURE_debug OR QT_FEATURE_debug_and_release
Condition values dump:
QT_FEATURE_debug = "ON"
QT_FEATURE_debug_and_release = "OFF"


CMake Error at cmake/QtBuildInformation.cmake:194 (message):
Check the configuration messages for an error that has occurred.
Call Stack (most recent call first):
cmake/QtBuildInformation.cmake:24 (qt_configure_print_summary)
cmake/QtBuildInternals/QtBuildInternalsConfig.cmake:548 (qt_print_feature_summary)
CMakeLists.txt:198 (qt_build_repo_end)


-- Configuring incomplete, errors occurred!
CMake Error at G:/qtbase-everywhere-src-6.8.0/cmake/QtProcessConfigureArgs.cmake:995 (message):
CMake exited with code 1.

解决方法:这是因为在64位的系统上选择x32的编译器引起的错误。根据自己的平台选择对应的编译器,例如,MSVC CL编译器的x64环境,否则启用optimize_size选项有相关报错信息。当然,不启用该选项的话,可正常编译,但得不偿失。

6.4.5   链接lib文件出现错误LNK2019

问题:链接lib文件报错,error LNK2019: 无法解析的外部符号。

1
2
3
4
5
6
7
8
9
10
11
12
-- Configuring done (10.5s)
-- Generating done (2.6s)
-- Build files have been written to: G:/qtdeclarative
[1569/4804] Linking CXX shared library bin\Qt6QmlXmlListModeld.dll
FAILED: bin/Qt6QmlXmlListModeld.dll lib/Qt6QmlXmlListModeld.lib
cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_dll --intdir=src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug --rc="C:\PROGRA~2\Windows Kits\10\bin\10.0.22621.0\x64\rc.exe" --mt="C:\PROGRA~2\Windows Kits\10\bin\10.0.22621.0\x64\mt.exe" --manifests -- "C:\PROGRA~2\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x64\link.exe" /nologo src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\QmlXmlListModel_autogen\mocs_compilation_Debug.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\cmake_pch.cxx.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\Debug\QmlXmlListModel_resource.rc.res src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\qqmlxmllistmodel.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\qmlxmllistmodel_qmltyperegistrations.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug.rcc\qrc_qmake_QtQml_XmlListModel.cpp.obj /out:bin\Qt6QmlXmlListModeld.dll /implib:lib\Qt6QmlXmlListModeld.lib /pdb:bin\Qt6QmlXmlListModeld.pdb /dll /version:6.5 /machine:x64 /debug -DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE lib\Qt6QmlModelsd.lib lib\Qt6Qmld.lib C:\Qt\qt6\lib\Qt6Network.lib C:\Qt\qt6\lib\Qt6Core.lib mpr.lib userenv.lib ws2_32.lib shell32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
LINK: command "C:\PROGRA~2\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.36.32532\bin\Hostx64\x64\link.exe /nologo src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\QmlXmlListModel_autogen\mocs_compilation_Debug.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\cmake_pch.cxx.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\Debug\QmlXmlListModel_resource.rc.res src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\qqmlxmllistmodel.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug\qmlxmllistmodel_qmltyperegistrations.cpp.obj src\qmlxmllistmodel\CMakeFiles\QmlXmlListModel.dir\Debug.rcc\qrc_qmake_QtQml_XmlListModel.cpp.obj /out:bin\Qt6QmlXmlListModeld.dll /implib:lib\Qt6QmlXmlListModeld.lib /pdb:bin\Qt6QmlXmlListModeld.pdb /dll /version:6.5 /machine:x64 /debug -DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE lib\Qt6QmlModelsd.lib lib\Qt6Qmld.lib C:\Qt\qt6\lib\Qt6Network.lib C:\Qt\qt6\lib\Qt6Core.lib mpr.lib userenv.lib ws2_32.lib shell32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:bin\Qt6QmlXmlListModeld.dll.manifest" failed (exit code 1120) with the following output:
正在创建库 lib\Qt6QmlXmlListModeld.lib 和对象 lib\Qt6QmlXmlListModeld.exp
qqmlxmllistmodel.cpp.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: __cdecl QtPrivate::ResultIteratorBase::~ResultIteratorBase(void)" (_imp??1ResultIteratorBase@QtPrivate@@QEAA@XZ),函数 "public: struct QQmlXmlListModelQueryResult const & __cdecl QFutureInterface<struct QQmlXmlListModelQueryResult>::resultReference(int)const " (?resultReference@?$QFutureInterface@UQQmlXmlListModelQueryResult@@@@QEBAAEBUQQmlXmlListModelQueryResult@@H@Z) 中引用了该符号
bin\Qt6QmlXmlListModeld.dll : fatal error LNK1120: 1 个无法解析的外部命令
[1598/4804] Automatic MOC for target Quick
ninja: build stopped: subcommand failed.

解决方式:这是启用debug-and-release编译源码导致的,debug和release同时编译易出问题,因此建议分开编译。

6.4.6   编译的字符报错或者其他问题

问题:编译可能提示找不到路径或者字符报错等其他问题,可能是由于中文路径引起。

解决方式:路径中不要含有中文字符,可以在磁盘根目录下操作,这样可保证路径总字符不会很多。

6.5   Qt各模块的介绍及其依赖项:

ModuleRequired submodulesDevelopment packages requiredDescription
qtbaseQt core, start with this.
qtimageformatslibmng-devSupport for loading various extra image formats

TIFF, MNG, WebP
qtsvgSupport for SVG vector graphics
qtshadertoolsTools for the cross-platform Qt shader pipeline
qttoolsqtdeclarativeQDoc requires clang to be installed (See section about documentation above):

clang-11 libclang-11-dev libclang-common-11-dev
Various Qt tools:
QtAssistant
Qt Designer
Qt Linguist
QDoc
etc
qtserialbusSerial bus (CAN bus, ModBus) support
qtserialportqtserialbusSerial port support
qtlocationqtserialportPositioning (GPS) and location (Map) services
qtdeclarativeqtshadertoolsQt Quick / QML
qtmultimediaqtdeclarativeFor ffmpeg backend (prefered backend since 6.5):
ffmpeg libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswresample-dev libswscale-dev

For gstreamer backend:
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad libgstreamer-plugins-bad1.0-dev gstreamer1.0-pulseaudio gstreamer1.0-tools gstreamer1.0-alsa

For pulseaudio support:
pulseaudio libpulse-dev

For plain ALSA:
libasound2-dev
Multimedia (audio/video) support
Audio play, record
Video play
Video input, capture
qt3d
qtquick3dA high-level API for creating 3D content and 3D user interfaces based on Qt Quick
qtquick3dphysicsA physics engine for use with Qt Quick 3D
qtdatavis3d
qtsensorsqtmultimediaSupport for various device sensors
qtnetworkauthNetwork authentication protocol support (OAuth)
qtconnectivitybluez libbluetooth-devBluetooth and NFC connectivity support
qtwebsocketsqtdeclarativeWebsockets support
qtchartsqtdeclarativeCharting controls
qtwaylandlibwayland-devWayland support
qtvirtualkeyboardqtsvgProvides on-screen keyboard
qtwebengineqtdeclarativeflex bison gperf libre2-dev libnss3-dev nodejs libdrm-dev libxdamage-dev libsnappy-devWebEngine.
qtgrpcSupport for gRPC
qthttpserverQt HTTP Server
qtspeechText To Speech with Flite
qt5compatUnsupported Qt 5 compatibility code.

7   Qt的许可协议和费用问题

使用LGPL协议开发闭源程序,若使用动态链接的形式,可以以任何形式发布应用程序,只需声明使用Qt开发即可。

8   参考资料

[1] Building Qt 6.5 submodules[EB/OL]. https://www.tal.org/tutorials/building-qt-65-sub-modules.
[2] 用 VS Code 搞 Qt6:编译附加模块[EB/OL]. https://www.cnblogs.com/tcjiaan/p/16575655.html.
[3] Building Qt 6 from Git[EB/OL]. https://wiki.qt.io/Building_Qt_6_from_Git.
[4] Obligations of the GPL and LGPL[EB/OL]. https://www.qt.io/licensing/open-source-lgpl-obligations.
[5] Qt 收费吗?[EB/OL]. https://blog.csdn.net/csyounth/article/details/7347182.
[6] Qt 的开源版本与商业版区别及 LGPL 与闭源程序[EB/OL]. https://blog.csdn.net/heli200482128/article/details/79305245.
[7] Qt5 怎么最小化编译,只编译 qtbase[EB/OL]. https://blog.csdn.net/jhkwei/article/details/107949403.
[8] Qt 5.15.0 编译指南[EB/OL]. https://blog.csdn.net/zxjohnson/article/details/106621457.
[9] 在 Mac 编译成功运行 qt5.15 源码:debug 和 release 版本[EB/OL]. https://xmuli.tech/posts/8b05b275/.
[10] 愿编程不再乱码 (含 Qt)-根因深究[EB/OL]. https://ifmet.cn/posts/c0862e62/.
[11] QT error: LNK2019: 无法解析的外部符号“__declspec(dllimport) public:[EB/OL]. https://blog.csdn.net/lifuran156/article/details/118935649.
[12] error LNK2019: 无法解析的外部符号”__declspec(dllimport)[EB/OL]. https://www.cnblogs.com/lihaozy/archive/2012/07/05/2577512.html.
[13] 配置Qt新建工程时默认支持C++14或C++17[EB/OL]. https://blog.csdn.net/no_say_you_know/article/details/121924999.
[14] 首次安装Qt后,创建项目时出现“No valid kits found” 的解决办法[EB/OL]. https://codeantenna.com/a/Mc08ZG5tEW.
[15] 教你使用windeployqt工具来进行Qt的打包发布[EB/OL]. https://blog.csdn.net/sinat_36264666/article/details/73305712.
[16] QT5实现语言国际化(中英文界面动态切换,超详细)[EB/OL]. https://blog.csdn.net/m0_49047167/article/details/108442111.
[17] Qt 项目(CMake)设置国际化支持[EB/OL]. https://blog.csdn.net/qq_33154343/article/details/114439385.
[18] QT使用Enigma Virtual Box打包exe[EB/OL]. https://blog.csdn.net/qq_40994692/article/details/113880198.
[19] Qt 实现单个EXE文件(绿色运行版) Enigma Virtual Box[EB/OL]. https://www.cnblogs.com/ybqjymy/p/13926394.html.
[20] Virus detection by Windows Defender in boxed exe[EB/OL]. http://forum.enigmaprotector.com/viewtopic.php?t=14841.