首先声明,本文并非原创,纯属搬运,内容来自一位叫做飞扬青春的大神的Gitee主页,主要是为了收藏下面介绍的100多个Qt开发经验。我本身也从事了两年了Qt开发,再转Qt开发以前用的都是MFC,我仔细的看了一遍下面列出的各条经验,只恨看到的太晚了,因为很多都是自己踩过的坑。比如qss的ANSI编码、嵌套窗口中主窗口无法接收鼠标移动事件等,又比如我用qss设置窗口样式,但是项目每次重新构建以后,样式表就会不生效等问题,也花了自己不少时间去解决,所以在这里转发大神的经验,留作以后参考和逐条的研究,也分享给更多正在学习Qt或者正在使用Qt进行程序开发的朋友们。
大神主页:
1.当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了。
2.定时器是个好东西,学会好使用它,有时候用QTimer::singleShot可以解决意想不到的问题。
3.打开creator,在构建套件的环境中增加MAKEFLAGS=-j8,可以不用每次设置多线程编译。珍爱时间和生命。新版的QtCreator已经默认就是j8。
4.如果你想顺利用QtCreator部署安卓程序,首先你要在AndroidStudio里面配置成功,把坑全部趟平。
5.很多时候找到Qt对应封装的方法后,记得多看看该函数的重载,多个参数的,你会发现不一样的世界,有时候会恍然大悟,原来Qt已经帮我们封装好了。
6.可以在pro文件中写上标记版本号+ico图标(Qt5才支持)
VERSION=2020.10.25RC_ICONS=
7.管理员运行程序,限定在MSVC编译器
QMAKE_LFLAGS+=/MANIFESTUAC:"level='requireAdministrator'uiAccess='false'"VS2013在XP运行
8.运行文件附带调试输出窗口
CONFIG+=consolepro
9.绘制平铺背景QPainter::drawTiledPixmap,绘制圆角矩形QPainter::drawRoundedRect(),而不是QPainter::drawRoundRect();
10.移除旧的样式
//移除原有样式style()-unpolish(ui-btn);//重新设置新的该控件的样式。style()-polish(ui-btn);
11.获取类的属性
constQMetaObject*metaobject=object-metaObject();intcount=metaobject-propertyCount();for(inti=0;icount;++i){QMetaPropertymetaproperty=metaobject-property(i);constchar*name=();QVariantvalue=object-property(name);qDebug()namevalue;}12.Qt内置图标封装在QStyle中,大概七十多个图标,可以直接拿来用。
SP_TitleBarMenuButton,SP_TitleBarMinButton,SP_TitleBarMaxButton,SP_TitleBarCloseButton,SP_MessageBoxInformation,SP_MessageBoxWarning,SP_MessageBoxCritical,SP_MessageBoxQuestion,
13.根据操作系统位数判断加载
win32{contains(DEFINES,WIN64){DESTDIR=${PWD}/../../bin64}else{DESTDIR=${PWD}/../../bin32}}14.Qt5增强了很多安全性验证,如果出现setGeometry:Unabletosetgeometry,请将该控件的可见移到加入布局之后。
15.可以将控件A添加到布局,然后控件B设置该布局,这种灵活性大大提高了控件的组合度,比如可以在文本框左侧右侧增加一个搜索按钮,按钮设置图标即可。
QPushButton*btn=newQPushButton;btn-resize(30,ui-lineEdit-height());QHBoxLayout*layout=newQHBoxLayout(ui-lineEdit);layout-setMargin(0);layout-addStretch();layout-addWidget(btn);
16.对QLCDNumber控件设置样式,需要将QLCDNumber的segmentstyle设置为flat。
17.巧妙的使用findChildren可以查找该控件下的所有子控件。findChild为查找单个。
//查找指定类名objectName的控件QListQWidget*widgets=*("widgetname");//查找所有QPushButtonQListQPushButton*allPButtons=*();//查找一级子控件,不然会一直遍历所有子控件QListQPushButton*childButtons=*(QString(),Qt::FindDirectChildrenOnly);18.巧妙的使用inherits判断是否属于某种类。
QTimer*timer=newQTimer;//QTimerinheritsQObjecttimer-inherits("QTimer");//returnstruetimer-inherits("QObject");//returnstruetimer-inherits("QAbstractButton");//returnsfalse19.使用弱属性机制,可以存储临时的值用于传递判断。可以通过widget-dynamicPropertyNames()列出所有弱属性名称,然后通过widget-property("name")取出对应的弱属性的值。
20.在开发时,无论是出于维护的便捷性,还是节省内存资源的考虑,都应该有一个qss文件来存放所有的样式表,而不应该将setStyleSheet写的到处都是。如果是初学阶段或者测试阶段可以直接UI上右键设置样式表,正式项目还是建议统一到一个qss样式表文件比较好,统一管理。
21.如果出现Z-orderassignment:isnotavalidwidget.错误提示,用记事本打开对应的ui文件,找到zorder/zorder为空的地方,删除即可。
22.善于利用QComboBox的addItem的第二个参数设置用户数据,可以实现很多效果,使用itemData取出来。
23.如果用了webengine模块,发布程序的时候带上+translations文件夹+resources文件夹。
24.默认Qt是一个窗体一个句柄,如果要让每个控件都拥有独立的句柄,设置下(Qt::AA_NativeWindows);
25.Qt+Android防止程序被关闭。
elseQApplicationa(argc,argv);();ifdef__GNUC__ifdef_MSC_VERif_MSC_VER=1100//VC++5.0以上if_MSC_VER=1300//VC2003以上if_MSC_VER=1500//VC2008以上if_MSC_VER=1700//VC2012以上if_MSC_VER=1900//VC2015以上//BorlandC++ifdef__CGWIN__ifdef__MINGW32__//windowsifdef_WIN64//64bitifdef_CONSOLE//控制台程序//Windows(95/98/Me/NT/2000/XP/Vista)和WindowsCE都定义了if(WINVER=0x0400)//Windows95/以上if(WINVER=0x0500)//WindowsMe/2000以上if(WINVER=0x0600)//WindowsVista以上//_WIN32_WINNT内核版本if(_WIN32_WINNT=0x0501)//WindowsXP以上打印版本信息message(qtversion:$QT_VERSION)下面是表示(QT_VER_MAJ,4){greaterThan(QT_VER_MIN,4){QT_ARCH是Qt5新增的,在Qt4上没效果表示arm平台构建套件contains(QT_ARCH,arm){}表示64位的构建套件contains(QT_ARCH,x86_64){}33.Qt最小化后恢复界面假死冻结,加上代码
voidshowEvent(QShowEvent*e){setAttribute(Qt::WA_Mapped);QWidget::showEvent(e);}34.获取标题栏高度:style()-pixelMetric(QStyle::PM_TitleBarHeight);PM_TitleBarHeight点进去你会发现新大陆。
35.设置高分屏属性以便支持2K4K等高分辨率,尤其是手机app。必须写在main函数的QApplicationa(argc,argv);的前面。
if
36.如果运行程序出现错误。
办法:打开注册表,找到HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\AppCompatFlags\Layers\,选中Layers键值,从右侧列表中删除自己的那个程序路径即可。
37.Qt内置了QFormLayout表单布局用于自动生成标签+输入框的组合的表单界面。
39.可以直接继承QSqlQueryModel实现自定义的QueryModel,比如某一列字体颜色,占位符,其他样式等,重写QVariantCustomSqlModel::data(constQModelIndexindex,introle)const。
40.Qt5以后提供了类QScroller直接将控件滚动。
//禁用横向滚动条ui-listWidget-setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用纵向滚动条ui-listWidget-setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//设置横向按照像素值为单位滚动ui-listWidget-setHorizontalScrollMode(QListWidget::ScrollPerPixel);//设置纵向按照像素值为单位滚动ui-listWidget-setVerticalScrollMode(QListWidget::ScrollPerPixel);//设置滚动对象以及滚动方式为鼠标左键拉动滚动QScroller::grabGesture(ui-listWidget,QScroller::LeftMouseButtonGesture);//还有个QScrollerProperties可以设置滚动的一些参数
41.如果使用sqlite数据库不想产生数据库文件,可以创建内存数据库。
QSqlDatabasedb=QSqlDatabase::addDatabase("QSQLITE");(":memory:");42.清空数据表并重置自增ID,sql=truncatetabletable_name。
43.Qtchart模块从开始自带,最低编译要求。在安装的时候记得勾选,默认不勾选。使用该模块需要引入命名空间。
if(definedwebkit)||(definedwebengine),去掉生成空的debug和release目录CONFIG-=debug_and_release。48.新版的Qtcreator增强了语法检查,会弹出很多警告提示等,可以在插件列表中关闭clang打头的几个即可,Help》AboutPlugins。也可以设置代码检查级别,Tools》Options》C++》CodeModel。
49.QSqlTableModel的rowCount方法,默认最大返回256,如果超过256,可以将表格拉到底部,会自动加载剩余的,每次最大加载256条数据,如果需要打印或者导出数据,记得最好采用sql语句去查询,而不是使用QSqlTableModel的rowCount方法。不然永远最大只会导出256条数据。
如果数据量很小,也可以采用如下方法:
//主动加载所有数据,不然获取到的行数=256while(model-canFetchMore()){model-fetchMore();}50.如果需要指定无边框窗体,但是又需要保留操作系统的边框特性,可以自由拉伸边框,可以使用
setWindowFlags(Qt::CustomizeWindowHint);51.在某些httppost数据的时候,如果采用的是字符串连接的数据发送,中文解析乱码的话,需要将中文进行URL转码。
QStringcontent="测试中文";QStringnote=().toPercentEncoding();52.Qt默认不支持大资源文件,比如添加了字体文件,需要pro文件开启。
CONFIG+=resources_big53.Qt中继承QWidget之后,样式表不起作用,解决办法有三个。强烈推荐方法一。
-方法一:设置属性this-setAttribute(Qt::WA_StyledBackground,true);
-方法二:改成继承QFrame,因为QFrame自带paintEvent函数已做了实现,在使用样式表时会进行解析和绘制。
-方法三:重新实现QWidget的paintEvent函数时,使用QStylePainter绘制。
voidWidget::paintEvent(QPaintEvent*){QStyleOptionoption;(this);QPainterpainter(this);style()-drawPrimitive(QStyle::PE_Widget,option,painter,this);}54.有时候在界面上加了弹簧,需要动态改变弹簧对应的拉伸策略,对应方法为changeSize,很多人会选择使用set开头去找,找不到的。
55.在使用QFile的过程中,不建议频繁的打开文件写入然后再关闭文件,比如间隔5ms输出日志,IO性能瓶颈很大,这种情况建议先打开文件不要关闭,等待合适的时机比如析构函数中或者日期变了需要重新变换日志文件的时候关闭文件。不然短时间内大量的打开关闭文件会很卡,文件越大越卡。
56.在很多网络应用程序,需要自定义心跳包来保持连接,不然断电或者非法关闭程序,对方识别不到,需要进行超时检测,但是有些程序没有提供心跳协议,此时需要启用系统层的保活程序,此方法适用于TCP连接。
intfd=tcpSocket-socketDescriptor();intkeepAlive=1;//开启keepalive属性,缺省值:0(关闭)intkeepIdle=5;//如果在5秒内没有任何数据交互,则进行探测,缺省值:7200(s)intkeepInterval=2;//探测时发探测包的时间间隔为2秒,缺省值:75(s)intkeepCount=2;//探测重试的次数,全部超时则认定连接失效,缺省值:9(次)setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,(void*)keepAlive,sizeof(keepAlive));setsockopt(fd,SOL_TCP,TCP_KEEPIDLE,(void*)keepIdle,sizeof(keepIdle));setsockopt(fd,SOL_TCP,TCP_KEEPINTVL,(void*)keepInterval,sizeof(keepInterval));setsockopt(fd,SOL_TCP,TCP_KEEPCNT,(void*)keepCount,sizeof(keepCount));57.如果程序打包好以后弹出提示ThisapplicationfailedtostartbecauseitcouldnotfindorloadtheQtplatformplugin一般都是因为platforms插件目录未打包或者打包错了的原因导致的。
58.非常不建议tr中包含中文,尽管现在的新版Qt支持中文到其他语言的翻译,但是很不规范,也不知道TMD是谁教的,tr的本意是包含英文,然后翻译到其他语言比如中文,现在大量的初学者滥用tr,如果没有翻译的需求,禁用tr,tr需要开销的,Qt默认会认为他需要翻译,会额外进行特殊处理。
59.很多人Qt和QtCreator傻傻分不清楚,经常问Qt什么版本结果发一个QtCreator的版本过来,QtCreator是使用Qt编写的集成开发环境IDE,和宇宙第一的VisualStudio一样,他可以是msvc编译器的(WIN对应的Qt集成安装环境中自带的QtCerator是msvc的),也可以是mingw编译的,还可以是gcc的。如果是自定义控件插件,需要集成到QtCreator中,必须保证该插件的动态库文件(dll或者so等文件)对应的编译器和Qt版本以及位数和QtCreator的版本完全一致才行,否则基本不大可能集成进去。特别注意的是Qt集成环境安装包中的Qt版本和QtCreator版本未必完全一致,必须擦亮眼睛看清楚,有些是完全一致的。
60.超过两处相同处理的代码,建议单独写成函数。代码尽量规范精简,比如if(a==123)要写成if(123==a),值在前面,再比如if(ok==true)要写成if(ok),if(ok==false)要写成if(!ok)等。
61.很多人问Qt嵌入式平台用哪个好,这里统一回答(当前时间节点2018年):imx6+335x比较稳定,性能高就用RK3288RK3399,便宜的话就用全志H3,玩一玩可以用树莓派香橙派。
62.对于大段的注释代码,建议用if将代码块包含起来,而不是将该段代码选中然后全部//,下次要打开这段代码的话,又需要重新选中一次取消,如果采用的是if(QT_VERSION=QT_VERSION_CHECK(5,0,0))ui-tableView-horizontalHeader()-setResizeMode(0,QHeaderView::Fixed);if
80.从Qt4转到Qt5,有些类的方法已经废弃或者过时了,如果想要在Qt5中启用Qt4的方法,比如QHeadVew的setMovable,可以在你的pro或者pri文件中加上一行即可:DEFINES+=QT_DISABLE_DEPRECATED_BEFORE=0
81.Qt中的QColor对颜色封装的很完美,支持各种转换,比如rgb、hsb、cmy、hsl,对应的是toRgb、toHsv、toCmyk、toHsl,还支持透明度设置,颜色值还能转成16进制格式显示。
QColorcolor(255,0,0,100);qDebug()()(QColor::HexArgb);//输出64ff0000
82.QVariant类型异常的强大,可以说是万能的类型,在进行配置文件的存储的时候,经常会用到QVariant的转换,QVariant默认自带了toString、toFloat等各种转换,但是还是不够,比如有时候需要从QVariant转到QColor,而却没有提供toColor的函数,这个时候就要用到万能办法。
if(()=="QColor"){QColorcolor=();QFontfont=();QStringnodeValue=(QColor::HexArgb);}83.Qt中的QString和constchar*之间转换,最好用toStdString().c_str()而不是toLocal8Bit().constData(),比如在setProperty中如果用后者,字符串中文就会不正确,英文正常。
84.Qt的信号槽机制非常牛逼,也是Qt的独特的核心功能之一,有时候我们在很多窗体中传递信号来实现更新或者处理,如果窗体层级比较多,比如窗体A的父类是窗体B,窗体B的父类是窗体C,窗体C有个子窗体D,如果窗体A一个信号要传递给窗体D,问题来了,必须先经过窗体B中转到窗体C再到窗体D才行,这样的话各种信号关联信号的connect会非常多而且管理起来比较乱,可以考虑增加一个全局的单例类AppEvent,公共的信号放这里,然后窗体A对应信号绑定到AppEvent,窗体D绑定AppEvent的信号到对应的槽函数即可,干净清爽整洁。
85.QTextEdit右键菜单默认英文的,如果想要中文显示,加载文件即可,一个Qt程序中可以安装多个翻译文件,不冲突。
86.Qt中有个全局的焦点切换信号focusChanged,可以用它做自定义的输入法。Qt4中默认会安装输入法上下文,比如在main函数打印会显示值,这个默认安装的输入法上下文,会拦截两个牛逼的信号QEvent::RequestSoftwareInputPanel和QEvent::CloseSoftwareInputPanel,以至于就算你安装了全局的事件过滤器依然识别不到这两个信号,你只需要在main函数执行(0)即可,意思是安装输入法上下文为空。
87.在以后,表格控件QTableWidget或者QTableView的默认最小列宽改成了15,以前的版本是0,所以在新版的qt中,如果设置表格的列宽过小,不会应用,取的是最小的列宽。所以如果要设置更小的列宽需要重新设置ui-tableView-horizontalHeader()-setMinimumSectionSize(0);
88.Qt源码中内置了一些未公开的不能直接使用的黑科技,都藏在对应模块的private中,比如gui-privatewidgets-private等,比如zip文件解压类QZipReader、压缩类QZipWriter就在gui-private模块中,需要在pro中引入QT+=gui-private才能使用。
include"QtGui/private/qzipwriter_"QZipReaderreader(dirPath);QStringpath("");//解压文件夹到当前目录(path);//文件夹名称QZipReader::FileInfofileInfo=(0);//解压文件QFilefile(filePath);(QIODevice::WriteOnly);((QString::fromLocal8Bit("%1").arg(filePath)));();();QZipWriter*writer=newQZipWriter(dirPath);//添加文件夹writer-addDirectory(unCompress);//添加文件QFilefile(filePath);(QIODevice::ReadOnly);writer-addFile(data,());();writer-close();89.理论上串口和网络收发数据都是默认异步的,操作系统自动调度,完全不会卡住界面,网上那些说收发数据卡住界面主线程的都是扯几把蛋,真正的耗时是在运算以及运算后的处理,而不是收发数据,在一些小数据量运算处理的项目中,一般不建议动用线程去处理,线程需要调度开销的,不要什么东西都往线程里边扔,线程不是万能的。只有当真正需要将一些很耗时的操作比如编码解码等,才需要移到线程处理。
90.在构造函数中获取控件的宽高很可能是不正确的,需要在控件首次显示以后再获取才是正确的,控件是在首次显示以后才会设置好正确的宽高值,记住是在首次显示以后,而不是构造函数或者程序启动好以后,如果程序启动好以后有些容器控件比如QTabWidget中的没有显示的页面的控件,你去获取宽高很可能也是不正确的,万无一失的办法就是首次显示以后去获取。
91.数据库处理一般建议在主线程,如果非要在其他线程,务必记得打开数据库也要在那个线程,即在那个线程使用数据库就在那个线程打开,不能打开数据库在主线程,执行sql在子线程,很可能出问题。
92.新版的QTcpServer类在64位版本的Qt下很可能不会进入incomingConnection函数,那是因为Qt5对应的incomingConnection函数参数变了,由之前的int改成了qintptr,改成qintptr有个好处,在32位上自动是quint32而在64位上自动是quint64,如果在Qt5中继续写的参数是int则在32位上没有问题在64位上才有问题,所以为了兼容Qt4和Qt5,必须按照不一样的参数写。
elsevoidincomingConnection(inthandle);if(QT_VERSIONQT_VERSION_CHECK(5,4,0))//下面两种方法都可以,Qt默认采用的是AA_UseDesktopOpenGLQCoreApplication::setAttribute(Qt::AA_UseOpenGLES);//QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);if0while(!()){QStringline=();appName(line);}();}97.用()读取QSS文件默认是ANSI格式,不支持UTF8,如果在QtCreator中打开qss文件来编辑保存,这样很可能导致qss加载以后没有效果。
voidfrmMain::initStyle(){//加载样式表QStringqss;//QFilefile(":/qss/");//QFilefile(":/qss/");QFilefile(":/qss/");if((QFile::ReadOnly)){else//用readAll读取默认支持的是ANSI格式,如果不小心用creator打开编辑过了很可能打不开qss=QLatin1String(());if(QT_VERSIONQT_VERSION_CHECK(5,0,0))tableView-horizontalHeader()-setSectionsClickable(false);if//鼠标按下即进入编辑模式if(edit){tableView-setEditTriggers(QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked);}else{tableView-setEditTriggers(QAbstractItemView::NoEditTriggers);}}104.在一些大的项目中,可能嵌套了很多子项目,有时候会遇到子项目依赖其他子项目的时候,比如一部分子项目用来生成动态库,一部分子项目依赖这个动态库进行编译,此时就需要子项目按照顺序编译。
TEMPLATE=subdirs#设置ordered参数以后会依次编译demodesignerexamplesCONFIG+=orderedSUBDIRS+=demoSUBDIRS+=designerSUBDIRS+=examples
105.MSVC编译器的选择说明
-如果是32位的Qt则编译器选择x86开头的
-如果是64位的Qt则编译器选择amd64开头的
-具体是看安装的Qt构建套件版本以及目标运行平台的系统位数和架构
-一般现在的电脑默认以64位的居多,选择amd64即可
-如果用户需要兼容32位的系统则建议选择32位的Qt,这样即可在32位也可以在64位系统运行
-诸葛大佬补充:x86/x64都是编译环境和运行环境相同,没有或。带下划线的就是交叉编译,前面是编译环境,后面是运行环境。
|名称|说明|
|------|------|
|x86|32/64位系统上编译在32/64位系统上运行|
|x86_amd64|32/64位系统上编译在64位系统上运行|
|x86_arm|32/64位系统上编译在arm系统上运行|
|amd64|64位系统上编译在64位系统上运行|
|amd64_x86|64位系统上编译在32/64位系统上运行|
|amd64_arm|64位系统上编译在arm系统上运行|
106.很多时候用QDialog的时候会发现阻塞了消息,而有的时候我们希望是后台的一些消息继续运行不要终止,此时需要做个设置。
QDialogdialog;(Qt::WindowModal);
107.很多初学者甚至几年工作经验的人,对多线程有很深的误解和滥用,尤其是在串口和网络通信这块,什么都往多线程里面丢,一旦遇到界面卡,就把数据收发啥的都搞到多线程里面去,殊不知绝大部分时候那根本没啥用,因为没找到出问题的根源。
-如果你没有使用wait***函数的话,大部分的界面卡都出在数据处理和展示中,比如传过来的是一张图片的数据,你需要将这些数据转成图片,这个肯定是耗时的;
-还有就是就收到的数据曲线绘制出来,如果过于频繁或者间隔过短,肯定会给UI造成很大的压力的,最好的办法是解决如何不要频繁绘制UI比如合并数据一起绘制等;
-如果是因为绘制UI造成的卡,那多线程也是没啥用的,因为UI只能在主线程;
-串口和网络的数据收发默认都是异步的,由操作系统调度的,如果数据处理复杂而且数据量大,你要做的是将数据处理放到多线程中;
-如果没有严格的数据同步需求,根本不需要调用wait***之类的函数来立即发送和接收数据,实际需求中大部分的应用场景其实异步收发数据就足够了;
-有严格数据同步需求的场景还是放到多线程会好一些,不然你wait***就卡在那边了;
-多线程是需要占用系统资源的,理论上来说,如果线程数量超过了CPU的核心数量,其实多线程调度可能花费的时间更多,各位在使用过程中要权衡利弊;
108.在嵌入式linux上,如果设置了无边框窗体,而该窗体中又有文本框之类的,发现没法产生焦点进行输入,此时需要主动激活窗体才行。
//这种方式设置的无边框窗体在嵌入式设备上无法产生焦点setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint|Qt::X11BypassWindowManagerHint);//需要在show以后主动激活窗体w-show();w-activateWindow();
109.QString的replace函数会改变原字符串,切记,他在返回替换后的新字符串的同时也会改变原字符串,我的乖乖!
110.QGraphicsEffect类的相关效果很炫,可以实现很多效果比如透明、渐变、阴影等,但是该类很耗CPU,如果不是特别需要一般不建议用,就算用也是要用在该部件后期不会发生频繁绘制的场景,不然会让你哭晕在厕所。
111.在不同的平台上文件路径的斜杠也是不一样的,比如linux系统一般都是/斜杠,而在windows上都是\\两个反斜杠,Qt本身程序内部无论在win还是linux都支持/斜杠的路径,但是一些第三方库的话可能需要转换成对应系统的路径,这就需要用到斜杠转换,Qt当然内置类方法。
QStringpath="C:/temp/";path=QDir::toNativeSeparators(path);//输出C:\\temp\\="C:\\temp\\";path=QDir::toNativeSeparators(path);//输出C:/temp/
112.巧用QMetaObject::invokeMethod方法可以实现很多效果,包括同步和异步执行,比如有个应用场景是在回调中,需要异步调用一个public函数,如果直接调用的话会发现不成功,此时需要使用QMetaObject::invokeMethod(obj,"fun",Qt::QueuedConnection);这种方式来就可以。invokeMethod函数有很多重载参数,可以传入返回值和执行方法的参数等。
113.Qt5中的信号是public的,可以在需要的地方直接emit即可,而在Qt4中信号是protected的,不能直接使用,需要定义一个public函数来emit。
114.版本开始官方不再提供安装包,只提供源码,可以自行编译或者在线安装,估计每次编译各种版本太麻烦,更多的是为了统计收集用户使用信息比如通过在线安装,后期可能会逐步加大商业化力度。











