Qt注意事项

前言

这篇博客记录的是写Qt时遇到的各种小坑,仅此记录一下。

1、资源文件

1.1、路径

在添加资源文件时,先添加前缀,一般使用“/”,比较方便。然后添加文件,添加的文件的路径一定要在.qrc文件的同层目录或者下层目录,不能在qrc文件的上层目录,不然无法识别路径。并且文件的路径不能包含中文和空格。

2、QML

2.1、QML添加图标

在QML中使用Button时,添加icon无法直接使用icon属性,而是使用icon.source来指定图片的url。但是处理完的图片会变成黑色,不知道是否还需要设置其他属性。暂时用Image解决问题。

3、QtCreator

3.1、项目名称

如果项目的target名称包含installer这种字符串,会导致编译出来的exe自动提升为管理员权限,导致QtCreator无法启动编译完的程序。并且运行结束后,会提示没有正确安装程序。此bug在win10上出现,win7没有。

4、Qt接口

4.1、QByteArray

先上一段bug代码

1
2
3
4
QByteArray buffer="test";

buffer.resize(1024);
QByteArray out = QCryptographicHash::hash(buffer, QCryptographicHash::Md5);

这个代码在我的开发机器上没有问题,每次加密出来的内容正确,但是在其他机器上运行出现bug,每次加密完的东西都不一样。这里我对resize这个接口没有仔细查看文档,文档已经说明resize只会分配空间,但是不会初始化,也就是说这地方是个未定义行为,导致结果不可预测。(其实c++的容器都是这样,以后需谨记)。

再上另外一段错误代码

1
2
char buffer[1024]="test";   //要求buffer的长度固定为1024
QByteArray out = QCryptographicHash::hash(buffer, QCryptographicHash::Md5);

这里看似没有问题,但是结果仍然不正确,是因为hash的接口参数列表,第一个参数是const QByteArray &data,也就是说char []传入进去会导致一个默认的类型转换,转换的结果就是丢失了原本填充的\0,只保留了test字符,导致加密之前的原始内容长度变了,所以结果也变了。所以在char[]转QByteArray的时候注意一定要明确长度。

4.2、Qt::Tool

  这是一个窗口属性,如果一个顶层窗口并且是最后一个窗口设置了这个属性,会导致关闭这个窗口时,进程并不会自动退出,也就是没有结束qApp的事件循环。并且windows的任务栏也没有该进程的图标。

4.3、QMenu

  QMainWindow上的菜单栏,假如想隐藏其中某个Menu(包含多个Action),有一些注意事项:

1
2
ui.menu->setVisible(false);//无效代码
ui.mene->menuAction()->setVisible(false);//正确代码

5、信号槽

5.1、槽函数命名

代码遇到这个警告:QMetaObject::connectSlotsByName: No matching signal for on_text_finished(QString),但是槽函数还是执行了。代码里面我使用了一个自定义信号 text(QString) ,然后使用了显式连接connect(this,&MainWindow::text,this,&MainWindow::on_text_finished);之所以会报错,这是因为当我们使用on_控件名称_信号名这种格式写槽函数时,Qt的connectSlotsByName函数会默认去查找finished这个信号,然后连接这个槽函数,但是这里没有定义这个信号。我们使用ui时,转到槽这个功能会自动生成对应格式的槽函数,然后connectSlotsByName函数就会按照对应关系隐式去连接槽和信号。比如:private slots: void on_action_triggered();在moc的时候就会自动去查找action这个控件的triggered信号,然后连接这个槽函数。所以我们自定义的槽函数不要按照Qt自动生成的格式来写。

6、OpenSSL

  Qt的网络库如果需要使用https或者其他依赖OpenSSL的协议,一般直接引入相关代码会报无法找到相关接口实现的bug,因为sdk的bin目录里面默认没有加入OpenSSL的两个dll,以前都是手动编译对应的版本,特别是mingw,后来发现在Tools/mingwxxx_xx/opt/bin目录以及存在该库文件,只需要拷贝到mingw的qt sdk的bin目录即可。

7、Qt程序发布与环境变量

  在windows平台开发Qt,在发布程序的时候,常规做法是打开二进制对应kit的命令行工具,然后执行windeployqt.exe target.exe,此时会将Qt程序所需要的依赖全部拷贝到当前目录下。如果你使用了其他不匹配的版本上对应的windeployqt,会导致拷贝过去的依赖版本不一致,然后启动失败。
  拷贝完成之后,目录如下图:

  这些依赖主要分为两种,一种是强依赖,是在编译的过程中通过编译指令引入的,比如Qt5Core.dll,如果这些库缺失那么程序直接无法启动。还有些依赖,比如分布在这些二级目录platforms目录下的qwindows.dll,这是一种插件,程序启动的时候会去指定目录下加载这些插件,如果关键插件丢失,程序也会启动失败。有些不影响启动的插件确实则不会影响程序的启动,只是会导致对应的功能不正常,比如imageformats中,有各种格式图片的解析插件,去掉其中一项只会影响对应的格式图片的加载解析功能。
  这里存在一个问题,为什么Qt程序能够自动找到这些插件的路径?原理就是通过环境变量。QT_PLUGIN_PATH这个环境变量就是用于指定所有插件的加载总入口目录,还有些细分的环境变量用于控制不同类型的插件目录,QT_QPA_PLATFORM_PATH,这个插件用于控制查找平台插件目录。一般在windows上开发的时候不需要考虑这些环境变量,但是在Linux上需要自己部署软件的启动环境的时候,比如写一个shell脚本一键启动Qt程序,就可以在shell中配置各种临时环境变量,这样就不需要手动永久修改系统的环境变量。


Qt注意事项
http://yoursite.com/2019/05/05/Qt注意事项/
作者
还在输入
发布于
2019年5月5日
许可协议