QT使用开发中踩过的坑和使用技巧

QT5.6.3使用开发中踩过的坑和使用技巧

使用技巧

1.Qt资源打开方式

在VS下使用QT插件进行开发,双击资源文件时不能用qrc编辑器打开的情况,右键选择打开方式,添加,找到qrcEditor.exe所在的路径(C:/User/Administrator/App Data/Local/Microsoft/VisualStudio/14.0/Extensions/12mkiltb.dmu/QrcEditor.exe),然后把它设置为默认打开方式。

2.Qt使用NetWork

Qt使用NetWork,需要加入Qt5NetWork.lib

3.使用QSound的程序迁移到其他机器没有声音

发布时需要带上很多QSound用到的动态库,一定要拷贝齐全,否则没有声音。window平台直接使用Qt自带的打包程序windeployqt,在QT的安装目录的bin文件夹下。
使用方法:
1.在开始菜单中找到QT目录进入QT命令行程序
2.cd到bin目录
3.cd切换到xxx.exe所在目录,输入命令windeployqt xxx.exe(xxx.exe是发布的程序名称,拷贝出来单独放在一个文件夹中最好)
4.删除生成的translate文件夹,不需用到
5.可以把与插件相关的动态库放置在plugins文件夹下(在QT安装目录下的plugins文件夹里的那些文件,保持一致的目录结构),然后在xxx.exe所在的同级目录下,创建一个文件qt.conf,内容为:

[Paths]
Prefix=.
Libraries=./dll
Plugins=plugins
Imports=imports
Qml2Imports=qml

4.Linux下打包方式

官方打包方式链接:Deploying an Application on X11 Platforms
动态编译QT迁移到其他机器要带上qt的.so动态库,Linux下没有提供打包工具,所以需要自己手动拷贝出所需的.so,下面的拷贝过程:
1.在编译生成的文件中新建一个脚本文件 install.sh,通过指令chmod 777 install.sh
2.向install.sh中写入以下的内容:

#!/bin/bash

LibDir=$PWD"/lib"
Target=$1

lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))

$(mkdir $LibDir)

for Variable in ${lib_array[@]}
do
       cp "$Variable" $LibDir
done

3.打开终端,输入./install.sh process(此处为可执行程序的名字)

(其中,process是运行脚本install.sh脚本的参数,
脚本实际调用了ldd process指令时获得process运行时需要哪些库,并将库都复制放到当前目录的lib文件夹中。)

运行完上述的指令后,同目录下会生成lib文件夹,这里我们将其称作process的库文件夹中,注意:这里要把lib里面的文件复制出来,并放到自己创建的文件夹的名字里面,不用复制lib文件夹。
4.进入QT的安装目录,找到platforms文件夹,将整个platforms文件夹复制到process文件夹中
5.将上文的install.sh文件放到process/platforms/中,运行./install.sh libqxcb.so,这时会得到lib文件夹——libqxcb.so的库文件夹
6.将libqxcb.so的库文件夹中的所有文件复制到process文件夹中,然后删除process/platforms/lib文件夹
7.在process文件夹中新建脚本文件process(程序的名称).sh,执行chmod 777 process.sh,并将以下内容写入:

#!/bin/sh
appname=`basename $0 | sed s,\.sh$,,`

dirname=`dirname $0`
tmp="${dirname#?}"

if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname
export LD_LIBRARY_PATH
$dirname/$appname "$@"

8.最后发布运行是,运行程序同名的.sh文件

踩过的坑

编译问题

1。编译问题,在VS下编译QT项目时有时不会自动把Generated Files下的文件加入编译,手动添加进去,同时需要注意的是,如果需要Debug和Release编译,不要同时把Generated Files下的Debug和Release生成的文件都加进去。

2。编译问题,有时候在修改ui文件,但是对应的源文件没有更新,此时可以把文件夹下的自动生成文件删除,重新编译

3。以上操作不能解决,多试几次,删除文件,移除文件,添加文件,重新编译,或者选择单独右键编译改动的文件

4。编译问题,“无法解析的外部符号 QMetaObject“ 诸如此类问题,均为带QT_OBJECT宏没有正确moc,尝试把相应的.h文件从项目中移除(注意不是删除),再重新添加,等待Generated Files下重新生成moc_xxx文件,重复此操作多遍,仍无法解决时,尝试把.h文件做一下修改,添加一个空格再删除,意在使.h文件发生变动,触发moc文件更新。

5。编译问题 ,编译过程中发现Moc’ing 报错,提示

>Missing value after ‘-I’
>xxxxx\Microsoft.CppCommon.targets(170,5):error MSB6006:"cmd.exe"已退出,代码为1。

使用文本编辑器打开项目文件(*.vcproj),将“-I$(NOINHERIT)”替换为“-I$(NOINHERIT)\”

qApp->quit退出问题

使用qApp->quit()退出程序,一些窗口的析构函数和closeevent事件得不到执行,程序就会退出,可能会出现假死的现象,需要显式delete或close。
我的问题场景在于,我的主窗口会创建一个登录窗口的指针,启动程序时登录窗口显示,主窗口不显示,在登录窗口点击退出时触发qApp->quit(),这时需要程序退出,但是主窗口没有被调用析构函数,登录窗口的指针也没有被释放,导致登录窗口还在显示,这时点击登录成功后显示主窗口,登录窗口隐藏,但是程序已经退出,主窗口的界面就是一直假死。

程序关闭进程仍存在

依然是上面的场景,登陆窗口点击退出后,有两句动作:

close();
emit ....	//发送信号告知主窗口登陆取消且退出

主窗口对应的槽函数中,对这个信号的处理是,销毁登陆窗口指针,退出程序
这里由于登陆窗口先是close,再被销毁指针,实际上进行了两次析构,这会导致崩溃,如果不发生崩溃,就会出现程序退出但进程存在的现象。

QIntValidator

使用QIntValidator设置最小值没有用

Linux打包后Qt程序启动错误

错误提示:“Failed to load platform plugin “xcb” while lauching"
这里的关键问题在于libqxcb.so库所要依赖的动态库找不到,网上查了很多说法,都是说没有把libqxcb.so库所要依赖的库拷全,然后我继续把install.sh放在libqxcb.so文件加下运行,重新生成一次lib文件,把lib文件夹下的.so文件都拷贝出来,发布,依然无法解决问题。辗转反侧研究了好久,直到看到这篇链接:https://stackoverflow.com/questions/17106315/failed-to-load-platform-plugin-xcb-while-launching-qt5-app-on-linux-without
得到的启发,反反复复看了很多次ldd libqxcb.so后,发现它所依赖的是libQt5DBus.so.5和libQt5XcbQpa.so.5,而我拷贝出来的是libQt5DBus.so.5.6.3和libQt5XcbQpa.so.5.6.3,前两个实际上是软链接,最后软链接指向后两个,所以,建立两个软链接到拷贝出来的这两个动态库,运行即可。
发布时,我选择在同名程序的.sh脚本文件上面手动添加两行建立软链接的命令:

ln -s libQt5DBus.so.5.6.3 libQt5DBus.so.5
ln -s libQt5XcbQpa.so.5.6.3 libQt5XcbQpa.so.5

关于QTableWidget

  • 某一列设置sectionModel为Stretch后不再会出现水平滚动条进行拉伸,也无法拖动列宽以用作显示
  • 水平拖动后标题会消失(未找到原因,解决方法通过尝试设置标题textAlignment,设置为AlignLeft之后成功不消失)

关于QDialogButtonBox

在一个对话框中放置一个QDialogButtonBox(包含确定和取消按钮)与直接放置两个QPushButton作确定和取消功能是不一样的。有时候我们要对点击确定按钮后做一些特殊动作,进行判断才确定这个对话框是否真正确定提交成功,如果使用QDialogButtonBox,连接QDialogButtonBox的accepted信号(即点击了按钮组中的确定键)到自定义的槽函数,不管槽函数中是否运行到调用accept()函数,这个对话框都会一点确定键就消失。使用两个QPushButton,连接确定按钮的clicked信号到自定义的槽函数,对话框会一直存在等待槽函数运行到调用accept()才会消失,如果在槽函数中做一些特殊动作,判断后直接返回而没有调用accept(),那么对话框会一直存在。
这种场景一般用于弹出对话框输入信息,点击OK会检查输入信息是否合法,不合法,提示,可以进行重新输入(因为对话框还没消失)。

待续。。。

猜你喜欢

转载自blog.csdn.net/zuolj/article/details/80793364
今日推荐