##使用技巧
###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
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。以上操作不能解决,多试几次,删除文件,移除文件,添加文件,重新编译,或者选择单独右键编译改动的文件
###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
###关于QDialogButtonBox
在一个对话框中放置一个QDialogButtonBox(包含确定和取消按钮)与直接放置两个QPushButton作确定和取消功能是不一样的。有时候我们要对点击确定按钮后做一些特殊动作,进行判断才确定这个对话框是否真正确定提交成功,如果使用QDialogButtonBox,连接QDialogButtonBox的accepted信号(即点击了按钮组中的确定键)到自定义的槽函数,不管槽函数中是否运行到调用accept()函数,这个对话框都会一点确定键就消失。使用两个QPushButton,连接确定按钮的clicked信号到自定义的槽函数,对话框会一直存在等待槽函数运行到调用accept()才会消失,如果在槽函数中做一些特殊动作,判断后直接返回而没有调用accept(),那么对话框会一直存在。
这种场景一般用于弹出对话框输入信息,点击OK会检查输入信息是否合法,不合法,提示,可以进行重新输入(因为对话框还没消失)。
待续。。。